@ciandt-flow/flow-ai-obs 0.12.0 → 0.12.1-beta.43

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,23 @@
1
- 'use strict';var child_process=require('child_process'),util=require('util'),R=require('fs'),M=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 R__default=/*#__PURE__*/_interopDefault(R);var M__default=/*#__PURE__*/_interopDefault(M);var me__default=/*#__PURE__*/_interopDefault(me);var Je__default=/*#__PURE__*/_interopDefault(Je);var Ke__default=/*#__PURE__*/_interopDefault(Ke);var Pe=Object.defineProperty;var ot=(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 _t=(t,e)=>{for(var r in e)Pe(t,r,{get:e[r],enumerable:true});};var xt={};_t(xt,{MacOsKeyVaultProvider:()=>yt});var At,yt,Bt=gt(()=>{"use strict";At=util.promisify(child_process.execFile),yt=class{static async isAvailable(){try{return R.accessSync("/usr/bin/security",R.constants.X_OK),!0}catch{return !1}}async getSecret(e,r){try{let{stdout:n}=await At("security",["find-generic-password","-w","-a",r,"-s",e]);return n.trim()||null}catch{return null}}async setSecret(e,r,n){await At("security",["add-generic-password","-U","-a",r,"-s",e,"-w",n]);}async deleteSecret(e,r){try{return await At("security",["delete-generic-password","-a",r,"-s",e]),!0}catch{return !1}}getStoragePath(){return "macOS Keychain"}};});var Ht={};_t(Ht,{LinuxKeyVaultProvider:()=>Ot});var Yt,Ot,Vt=gt(()=>{"use strict";Yt=util.promisify(child_process.execFile),Ot=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 R.accessSync(r,R.constants.X_OK),!0}catch{}return !1}async getSecret(e,r){try{let{stdout:n}=await Yt("secret-tool",["lookup","service",e,"account",r]);return n.trim()||null}catch{return null}}async setSecret(e,r,n){await new Promise((i,s)=>{let o=child_process.spawn("secret-tool",["store","--label",e,"service",e,"account",r]);o.on("error",s),o.on("close",c=>{c===0?i():s(new Error(`secret-tool exited with code ${c}`));}),o.stdin.write(n),o.stdin.end();});}async deleteSecret(e,r){try{return await Yt("secret-tool",["clear","service",e,"account",r]),!0}catch{return !1}}getStoragePath(){return "Linux Secret Service (libsecret)"}};});var Gt={};_t(Gt,{WindowsKeyVaultProvider:()=>kt});var kt,Wt=gt(()=>{"use strict";kt=class{static async isAvailable(){try{return await ot("keytar").getPassword("__flow_probe__","__flow_probe__"),!0}catch{return !1}}async getSecret(e,r){return ot("keytar").getPassword(e,r)}async setSecret(e,r,n){await ot("keytar").setPassword(e,r,n);}async deleteSecret(e,r){return ot("keytar").deletePassword(e,r)}getStoragePath(){return "Windows Credential Manager"}};});var Ne="https://flow.ciandt.com";function D(){let t=process.env.FLOW_BASE_URL;return t&&t.trim()?t.trim():Ne}function W(){let t=D();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 it={SERVICE:"flow-plugins-cli",ACCOUNT_TOKEN:"token-cache"},at="FLOW-nodejs",ct="config.json",Tt={SCOPE_NAME:"flow-ai-obs",SCOPE_VERSION:"0.1.0"};var _={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"};var J={REQUEST_TIMEOUT_MS:1e4,MAX_RETRY_ATTEMPTS:3,RETRY_DELAY_MS:1e3};var O={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",k={TOOL_INPUT:2e4,TOOL_OUTPUT:2e4,TRACE_OUTPUT:2e4,USER_INSTRUCTION:1e4,TRACE_INPUT:5e4};function St(){let t=D();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 K(){let t=me__default.default.homedir();if(process.platform==="darwin")return M__default.default.join(t,"Library","Preferences",at,ct);if(process.platform==="win32"){let r=process.env.APPDATA??M__default.default.join(t,"AppData","Roaming");return M__default.default.join(r,at,ct)}let e=process.env.XDG_CONFIG_HOME??M__default.default.join(t,".config");return M__default.default.join(e,at,ct)}function ht(){try{let t=R__default.default.readFileSync(K(),"utf8");return JSON.parse(t)}catch{return {}}}function Mt(t){let e=K();R__default.default.mkdirSync(M__default.default.dirname(e),{recursive:true}),R__default.default.writeFileSync(e,JSON.stringify(t,null,2),{encoding:"utf8",mode:384});}var q=class{static isAvailable(){return true}static hasExistingData(){try{if(!R__default.default.existsSync(K()))return !1;let e=JSON.parse(R__default.default.readFileSync(K(),"utf8"));return !!(e&&e.credentials)}catch{return false}}async getSecret(e,r){let n=ht(),i=Et[r]??r,s=n[i];return s?typeof s=="string"?s:JSON.stringify(s):null}async setSecret(e,r,n){let i=ht(),s=Et[r]??r;if(r==="token-cache")try{i[s]=JSON.parse(n);}catch{i[s]=n;}else i[s]=n;Mt(i);}async deleteSecret(e,r){let n=ht(),i=Et[r]??r;return i in n?(delete n[i],Mt(n),true):false}getStoragePath(){return `config.json (unencrypted) \u2014 ${K()}`}};async function Jt(){return process.env[_.FLOW_OBS_USE_JSON_VAULT]==="1"?new q:await Ye()??new q}async function Ye(){switch(process.platform){case "darwin":{let{MacOsKeyVaultProvider:t}=await Promise.resolve().then(()=>(Bt(),xt));return await t.isAvailable()?new t:null}case "linux":{let{LinuxKeyVaultProvider:t}=await Promise.resolve().then(()=>(Vt(),Ht));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=it.SERVICE,jt=it.ACCOUNT_TOKEN,wt=null;function qt(){return wt||(wt=Jt()),wt}async function Lt(t){await(await qt()).setSecret(Kt,jt,JSON.stringify({accessToken:t.accessToken,expiresAt:t.expiresAt,lastAuthCheckAt:t.lastAuthCheckAt}));}async function Rt(){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 It(){let t=await Rt();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=M.join(me.tmpdir(),Dt);function a(...t){if(process.env[_.FLOW_OBS_DEBUG]!=="1")return;let e=`[${new Date().toISOString()}] ${t.join(" ")}
2
- `;try{R.writeFileSync(We,e,{flag:"a"});}catch(r){process.stderr.write(`[flow-obs debug ERROR] ${r.message}
3
- `);}}var b=class extends Error{statusCode;constructor(e,r=0){super(e),this.name="AuthError",this.statusCode=r;}},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 Xt={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 Xe(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}`:"")),Xt[n.error]))return new b(Xt[n.error],t)}catch{}return t===401||t===403||t===500?new b("Invalid credentials",t):t>=400&&t<500?new b("Authentication request was rejected",t):new Error("Authentication service unavailable, please try again later")}function X(t){return new Promise((e,r)=>{try{qe(t.tenant);}catch(p){return r(p)}let n=JSON.stringify({clientSecret:t.clientSecret}),i=new URL(W().AUTH_ENGINE),s=i.protocol==="https:",o={hostname:i.hostname,port:i.port||(s?443:80),path:i.pathname+i.search,method:"POST",headers:{"Content-Type":"application/json","Content-Length":Buffer.byteLength(n),FlowTenant:t.tenant}};a("getToken",`requesting token tenant=${t.tenant} host=${o.hostname} path=${o.path}`);let l=(s?Je__default.default:Ke__default.default).request(o,p=>{let T=[];p.on("data",S=>T.push(S)),p.on("end",()=>{let S=T.join("");if((p.statusCode??0)>=400)return r(Xe(p.statusCode??0,S));let m;try{m=JSON.parse(S);}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();if(!m.access_token)return r(new Error("Auth engine returned an empty access token. Check FLOW_BASE_URL and credentials."));e({accessToken:m.access_token,expiresAt:g});});});l.on("error",p=>r(new Error(`Network error: ${p.message}`))),l.setTimeout(J.REQUEST_TIMEOUT_MS,()=>{l.destroy(new Error("Request timeout"));}),l.write(n),l.end();})}var ze=[/^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 ze.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 ut(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:i,tenant:s}=r;return !n||!i||!s?null:{clientId:n,clientSecret:i,tenant:s}}catch{return null}}function lt(t){let e;try{e=new URL(t);}catch{throw new Error(`Invalid URL: ${t}`)}let r=process.env[_.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 zt(){let t=ut(process.env[_.ANTHROPIC_AUTH_TOKEN]);return t?{user:await It().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 Rt();if(r?.lastAuthCheckAt!==e){a("getOrRefreshToken",`daily auth check (last: ${r?.lastAuthCheckAt??"never"})`);let s=J.MAX_RETRY_ATTEMPTS;for(let o=1;o<=s;o++)try{let c=await X(t);try{await Lt({...c,lastAuthCheckAt:e});}catch(l){a("getOrRefreshToken",`saveTokenCache failed (non-fatal): ${l.message}`);}return a("getOrRefreshToken",`daily check passed (attempt ${o}), expires=${c.expiresAt}`),c.accessToken}catch(c){if(c instanceof b){if(c.statusCode!==500)throw a("getOrRefreshToken",`daily check auth error (${c.statusCode}) \u2014 propagating immediately`),c;if(o<s){a("getOrRefreshToken",`daily check 500 error (attempt ${o}/${s}) \u2014 retrying in 1s`),await new Promise(l=>setTimeout(l,J.RETRY_DELAY_MS));continue}throw a("getOrRefreshToken",`daily check failed after ${s} attempts \u2014 propagating`),c}a("getOrRefreshToken",`daily check network error \u2014 using cache: ${c.message}`);break}}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 i=await X(t);try{await Lt({...i,lastAuthCheckAt:e});}catch(s){a("getOrRefreshToken",`token cache save failed (non-fatal): ${s.message}`);}return a("getOrRefreshToken",`token refreshed, expires=${i.expiresAt}`),i.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 x(){let t=[],e=process.env[_.ANTHROPIC_MODEL]??"",r=ut(process.env[_.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:"",i=process.env[_.FLOW_TELEMETRY]==="true",s=process.env[_.LANGFUSE_BASE_URL],o=process.env[_.LANGFUSE_PUBLIC_KEY],c=process.env[_.LANGFUSE_SECRET_KEY];if(i&&s&&o&&c){let m="",g=n;r&&(m=await It().catch(()=>null)??r.clientId);let E={user:m??"",tenant:g??"",team:"",project:"",model:e};t.push({mode:"direct",...nr(lt(s),o,c),...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 l;try{l=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 T={user:Qe(l)??r.clientId,tenant:n,team:"",project:"",model:e},S=process.env[_.FLOW_TELEMETRY_GATEWAY]??D();return t.push({mode:"gateway",...rr(lt(S),{accessToken:l}),...T}),t}function w(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 z(){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 A(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=M.normalize(me.tmpdir())+M.sep;function mr(t,e){let r=M.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(M.join(me.tmpdir(),`flow-obs-${t}.json`),fr)}function B(t){let e;try{e=Nt(t);}catch{return null}if(!R.existsSync(e))return null;try{return JSON.parse(R.readFileSync(e,"utf8"))}catch{return null}}function Y(t,e){R.writeFileSync(Nt(t),JSON.stringify(e),{encoding:"utf8",mode:384});}function bt(t){try{R.unlinkSync(Nt(t));}catch{}}function re(t){if(!t||!R.existsSync(t))return null;try{let e=R.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 Ut(t){if(!t||!R.existsSync(t))return null;try{let e=R.readFileSync(t,"utf8").trimEnd().split(`
6
- `),r=[],n=0,i=0;for(let s=e.length-1;s>=0;s--)try{let o=JSON.parse(e[s]);if(o.type==="user")break;if(o.type==="assistant"){let l=(o.message?.content??[]).filter(T=>T.type==="text").map(T=>T.text??"").join("");l&&r.unshift(l);let p=o.message?.usage??{};n+=(p.input_tokens??0)+(p.cache_read_input_tokens??0)+(p.cache_creation_input_tokens??0),i+=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'),h=require('fs'),G=require('path'),st=require('os'),cr=require('https'),lr=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 h__namespace=/*#__PURE__*/_interopNamespace(h);var G__namespace=/*#__PURE__*/_interopNamespace(G);var st__namespace=/*#__PURE__*/_interopNamespace(st);var cr__default=/*#__PURE__*/_interopDefault(cr);var lr__default=/*#__PURE__*/_interopDefault(lr);var Ve=Object.defineProperty;var ft=(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 dt=(t,e,r)=>()=>{if(r)throw r[0];try{return t&&(e=t(t=0)),e}catch(n){throw r=[n],n}};var wt=(t,e)=>{for(var r in e)Ve(t,r,{get:e[r],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 Lt(){let t=B();return {API_URL:process.env.FLOW_METRICS_URL||`${t}/metrics-collector-api/log-event`,BOOSTER:"flow-ai-obs"}}var je,dn,mt,gt,Et,Rt,g,Q,Kt,k,W,Jt,R,T=dt(()=>{"use strict";je="https://flow.ciandt.com";dn=H(),mt={SERVICE:"flow-plugins-cli",ACCOUNT_CREDS:"credentials",ACCOUNT_TOKEN:"token-cache"},gt="FLOW-nodejs",Et="config.json",Rt={SCOPE_NAME:"flow-ai-obs",SCOPE_VERSION:"0.1.0"},g={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_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",FLOW_API_KEY:"FLOW_API_KEY",OTEL_EXPORTER_OTLP_HEADERS:"OTEL_EXPORTER_OTLP_HEADERS",FLOW_BASE_URL:"FLOW_BASE_URL"},Q={REQUEST_TIMEOUT_MS:1e4,MAX_RETRY_ATTEMPTS:3,RETRY_DELAY_MS:1e3},Kt={LOCK_STALE_MS:3e4,CONNECTIVITY_MAX_RETRY:3,CONNECTIVITY_RETRY_MS:2e3,CLI:"flow-ai-obs "},k={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},W={API_KEY_MAX_LENGTH:1024,API_KEY_PATTERN:/^[\x21-\x7E]+$/,EMAIL_MAX_LENGTH:254,EMAIL_HEADER_PATTERN:/^[\x21-\x7E]+$/},Jt="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 qt={};wt(qt,{MacOsKeyVaultProvider:()=>bt});var vt,bt,zt=dt(()=>{"use strict";vt=util.promisify(child_process.execFile),bt=class{static async isAvailable(){try{return h.accessSync("/usr/bin/security",h.constants.X_OK),!0}catch{return !1}}async getSecret(e,r){try{let{stdout:n}=await vt("security",["find-generic-password","-w","-a",r,"-s",e]);return n.trim()||null}catch{return null}}async setSecret(e,r,n){await vt("security",["add-generic-password","-U","-a",r,"-s",e,"-w",n]);}async deleteSecret(e,r){try{return await vt("security",["delete-generic-password","-a",r,"-s",e]),!0}catch{return !1}}getStoragePath(){return "macOS Keychain"}};});var Qt={};wt(Qt,{LinuxKeyVaultProvider:()=>Nt});var Zt,Nt,te=dt(()=>{"use strict";Zt=util.promisify(child_process.execFile),Nt=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 h.accessSync(r,h.constants.X_OK),!0}catch{}return !1}async getSecret(e,r){try{let{stdout:n}=await Zt("secret-tool",["lookup","service",e,"account",r]);return n.trim()||null}catch{return null}}async setSecret(e,r,n){await new Promise((s,o)=>{let i=child_process.spawn("secret-tool",["store","--label",e,"service",e,"account",r]);i.on("error",o),i.on("close",c=>{c===0?s():o(new Error(`secret-tool exited with code ${c}`));}),i.stdin.write(n),i.stdin.end();});}async deleteSecret(e,r){try{return await Zt("secret-tool",["clear","service",e,"account",r]),!0}catch{return !1}}getStoragePath(){return "Linux Secret Service (libsecret)"}};});var ee={};wt(ee,{WindowsKeyVaultProvider:()=>Ut});var Ut,re=dt(()=>{"use strict";Ut=class{static async isAvailable(){try{return await ft("keytar").getPassword("__flow_probe__","__flow_probe__"),!0}catch{return !1}}async getSecret(e,r){return ft("keytar").getPassword(e,r)}async setSecret(e,r,n){await ft("keytar").setPassword(e,r,n);}async deleteSecret(e,r){return ft("keytar").deletePassword(e,r)}getStoragePath(){return "Windows Credential Manager"}};});T();T();var It={credentials:"credentials","token-cache":"tokenCache"};function tt(){let t=st__namespace.default.homedir();if(process.platform==="darwin")return G__namespace.default.join(t,"Library","Preferences",gt,Et);if(process.platform==="win32"){let r=process.env.APPDATA??G__namespace.default.join(t,"AppData","Roaming");return G__namespace.default.join(r,gt,Et)}let e=process.env.XDG_CONFIG_HOME??G__namespace.default.join(t,".config");return G__namespace.default.join(e,gt,Et)}function Pt(){try{let t=h__namespace.default.readFileSync(tt(),"utf8");return JSON.parse(t)}catch{return {}}}function Xt(t){let e=tt();h__namespace.default.mkdirSync(G__namespace.default.dirname(e),{recursive:true}),h__namespace.default.writeFileSync(e,JSON.stringify(t,null,2),{encoding:"utf8",mode:384});}var rt=class{static isAvailable(){return true}static hasExistingData(){try{if(!h__namespace.default.existsSync(tt()))return !1;let e=JSON.parse(h__namespace.default.readFileSync(tt(),"utf8"));return !!(e&&e.credentials)}catch{return false}}async getSecret(e,r){let n=Pt(),s=It[r]??r,o=n[s];return o?typeof o=="string"?o:JSON.stringify(o):null}async setSecret(e,r,n){let s=Pt(),o=It[r]??r;if(r==="token-cache")try{s[o]=JSON.parse(n);}catch{s[o]=n;}else s[o]=n;Xt(s);}async deleteSecret(e,r){let n=Pt(),s=It[r]??r;return s in n?(delete n[s],Xt(n),true):false}getStoragePath(){return `config.json (unencrypted) \u2014 ${tt()}`}};async function ne(){return process.env[g.FLOW_OBS_USE_JSON_VAULT]==="1"?new rt:await nr()??new rt}async function nr(){switch(process.platform){case "darwin":{let{MacOsKeyVaultProvider:t}=await Promise.resolve().then(()=>(zt(),qt));return await t.isAvailable()?new t:null}case "linux":{let{LinuxKeyVaultProvider:t}=await Promise.resolve().then(()=>(te(),Qt));return await t.isAvailable()?new t:null}case "win32":{let{WindowsKeyVaultProvider:t}=await Promise.resolve().then(()=>(re(),ee));return await t.isAvailable()?new t:null}default:return null}}T();var se=mt.SERVICE;mt.ACCOUNT_CREDS;var oe=mt.ACCOUNT_TOKEN,Ct=null;function ie(){return Ct||(Ct=ne()),Ct}async function Ft(t){await(await ie()).setSecret(se,oe,JSON.stringify({accessToken:t.accessToken,expiresAt:t.expiresAt,lastAuthCheckAt:t.lastAuthCheckAt}));}async function $t(){let e=await(await ie()).getSecret(se,oe);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 nt(){let t=await $t();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}}T();T();var ar=G.join(st.tmpdir(),Jt);function a(...t){if(process.env[g.FLOW_OBS_DEBUG]!=="1")return;let e=`[${new Date().toISOString()}] ${t.join(" ")}
2
+ `;try{h.writeFileSync(ar,e,{flag:"a"});}catch(r){process.stderr.write(`[flow-obs debug ERROR] ${r.message}
3
+ `);}}var U=class extends Error{statusCode;constructor(e,r=0){super(e),this.name="AuthError",this.statusCode=r;}},ur=/^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$|^[a-z0-9]$/;function pr(t){if(!ur.test(t))throw new Error(`Invalid tenant value: "${t}". Tenant must be lowercase alphanumeric and hyphens (1-64 chars).`)}var ae={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 fr(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}`:"")),ae[n.error]))return new U(ae[n.error],t)}catch{}return t===401||t===403||t===500?new U("Invalid credentials",t):t>=400&&t<500?new U("Authentication request was rejected",t):new Error("Authentication service unavailable, please try again later")}function Y(t){return new Promise((e,r)=>{try{pr(t.tenant);}catch(p){return r(p)}let n=JSON.stringify({clientSecret:t.clientSecret}),s=new URL(H().AUTH_ENGINE),o=s.protocol==="https:",i={hostname:s.hostname,port:s.port||(o?443:80),path:s.pathname+s.search,method:"POST",headers:{"Content-Type":"application/json","Content-Length":Buffer.byteLength(n),FlowTenant:t.tenant}};a("getToken",`requesting token tenant=${t.tenant} host=${i.hostname} path=${i.path}`);let l=(o?cr__default.default:lr__default.default).request(i,p=>{let S=[];p.on("data",m=>S.push(m)),p.on("end",()=>{let m=S.join("");if((p.statusCode??0)>=400)return r(fr(p.statusCode??0,m));let _;try{_=JSON.parse(m);}catch{return r(new Error("Invalid response from auth engine"))}let E=_.expires_at??new Date(Date.now()+(_.expires_in??3600)*1e3).toISOString();if(!_.access_token)return r(new Error("Auth engine returned an empty access token. Check FLOW_BASE_URL and credentials."));e({accessToken:_.access_token,expiresAt:E});});});l.on("error",p=>r(new Error(`Network error: ${p.message}`))),l.setTimeout(Q.REQUEST_TIMEOUT_MS,()=>{l.destroy(new Error("Request timeout"));}),l.write(n),l.end();})}T();T();!process.env.NO_COLOR&&process.stdout.isTTY;function _t(){if(process.env.WSL_DISTRO_NAME&&process.platform==="linux"){let t=process.env.USERPROFILE;if(!t){let r=child_process.spawnSync("cmd.exe",["/c","echo","%USERPROFILE%"],{encoding:"utf8",timeout:5e3}).stdout?.trim();r&&/^[A-Za-z]:\\/.test(r)&&(t=r);}if(t){let e=t.replace(/^([A-Za-z]):/,(r,n)=>`/mnt/${n.toLowerCase()}`).replace(/\\/g,"/");return G__namespace.join(e,".claude","settings.json")}return G__namespace.join(st__namespace.homedir(),".claude","settings.json")}if(process.platform==="win32"){let t=process.env.USERPROFILE||st__namespace.homedir();return G__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 G__namespace.join(e,".claude","settings.json")}return G__namespace.join(st__namespace.homedir(),".claude","settings.json")}var Er=Kt.LOCK_STALE_MS;function _r(t){try{let e=h__namespace.statSync(t);Date.now()-e.mtimeMs>Er&&h__namespace.unlinkSync(t);}catch{}try{h__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 Sr(t){try{h__namespace.unlinkSync(t);}catch{}}var ot;function ue(t){if(ot===void 0)try{let r=h__namespace.readFileSync(_t(),"utf8");ot=JSON.parse(r).env??null;}catch{ot=null;}if(!ot)return null;let e=ot[t];return typeof e=="string"?e:null}function pe(t){let e=_t(),r=e+".lock";h__namespace.mkdirSync(G__namespace.dirname(e),{recursive:true}),_r(r);try{let n={};try{n=JSON.parse(h__namespace.readFileSync(e,"utf8"));}catch{}(!n.env||typeof n.env!="object")&&(n.env={}),Object.assign(n.env,t),h__namespace.writeFileSync(e,JSON.stringify(n,null,2)+`
4
+ `,{encoding:"utf8",mode:384});try{h__namespace.chmodSync(e,384);}catch{}}finally{Sr(r);}}T();function fe(){return !!process.env[g.FLOW_USER_EMAIL]||!!ue(g.FLOW_USER_EMAIL)}function Dt(t){a("maybePersistUserEmail",`${t}: starting`);let e=t==="api-key"?`\u26A0\uFE0F flow-ai-obs: FLOW_USER_EMAIL is not set. Configure it with:
5
+ flow-ai-obs init --custom-email <EMAIL>
6
+ `:`\u26A0\uFE0F flow-ai-obs: FLOW_USER_EMAIL is not set and could not be derived from token.
7
+ Run: flow-ai-obs init
8
+ `;return nt().then(r=>{if(r){let n=r.split(/[\r\n]/)[0].replace(/[\x00-\x1F\x7F]/g,"").trim();if(!n)return;let s=n.indexOf("@"),o=n.slice(s+1);if(!(n.length<=254&&W.EMAIL_HEADER_PATTERN.test(n)&&(n.match(/@/g)??[]).length===1&&s>0&&s<n.length-1&&o.includes("."))){a("maybePersistUserEmail",`${t}: email from token failed basic validation \u2014 skipping persist`);return}try{pe({[g.FLOW_USER_EMAIL]:n}),a("maybePersistUserEmail",`${t}: persisted FLOW_USER_EMAIL from OAuth token`);}catch(c){a("maybePersistUserEmail",`${t}: FLOW_USER_EMAIL write failed: ${c.message}`),process.stderr.write(`\u26A0\uFE0F flow-ai-obs: could not persist FLOW_USER_EMAIL to settings.json.
9
+ Run: flow-ai-obs init
10
+ `);}}else process.stderr.write(e);}).catch(r=>{a("maybePersistUserEmail",`${t}: getEmailFromToken failed: ${r.message}`);})}var Tr=[/^localhost\.?$/i,/^127\./,/^10\./,/^172\.(1[6-9]|2\d|3[01])\./,/^192\.168\./,/^169\.254\./,/^0\.0\.0\.0$/,/^::1$/,/^\[::1\]$/,/^\[::ffff:/i,/^\[f[cd]/i,/^\[fe80:/i,/^metadata\.google\.internal\.?$/i,/^metadata\.azure\.internal\.?$/i,/(?:^|\.)localtest\.me\.?$/i,/(?:^|\.)lvh\.me\.?$/i,/(?:^|\.)vcap\.me\.?$/i];function hr(t){return Tr.some(e=>e.test(t))}function yr(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 Tt(t){if(!t)return null;try{let e=t.split(".");if(e.length<2)return null;let r=JSON.parse(Buffer.from(e[1].replace(/-/g,"+").replace(/_/g,"/"),"base64").toString("utf8")),{clientId:n,clientSecret:s,tenant:o}=r;return !n||!s||!o?null:{clientId:n,clientSecret:s,tenant:o}}catch{return null}}function St(t){let e;try{e=new URL(t);}catch{throw new Error(`Invalid URL: ${t}`)}let r=process.env[g.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&&hr(e.hostname))throw new Error(`SSRF: private/loopback host not allowed: ${e.hostname}`);return t}async function de(){let t=Tt(process.env[g.ANTHROPIC_AUTH_TOKEN]);return t?{user:await nt().catch(()=>null)??t.clientId,tenant:t.tenant}:{user:"",tenant:""}}function Ar(){let t=process.env[g.FLOW_API_KEY];if(!t)return null;let e=t.replace(/[\r\n]/g,"").trim();return e?e.length>W.API_KEY_MAX_LENGTH?(a("resolveApiKey",`FLOW_API_KEY exceeds ${W.API_KEY_MAX_LENGTH} chars \u2014 rejected`),null):W.API_KEY_PATTERN.test(e)?e:(a("resolveApiKey","FLOW_API_KEY contains non-printable or control characters \u2014 rejected"),null):null}function Or(){return new Date().toISOString().slice(0,10)}async function kr(t){let e=Or(),r=await $t();if(r?.lastAuthCheckAt!==e){a("getOrRefreshToken",`daily auth check (last: ${r?.lastAuthCheckAt??"never"})`);let o=Q.MAX_RETRY_ATTEMPTS;for(let i=1;i<=o;i++)try{let c=await Y(t);try{await Ft({...c,lastAuthCheckAt:e});}catch(p){a("getOrRefreshToken",`saveTokenCache failed (non-fatal): ${p.message}`);}return a("getOrRefreshToken",`daily check passed (attempt ${i}), expires=${c.expiresAt}`),Ar()?fe()||await Dt("api-key"):await Dt("oauth"),c.accessToken}catch(c){if(c instanceof U){if(c.statusCode!==500)throw a("getOrRefreshToken",`daily check auth error (${c.statusCode}) \u2014 propagating immediately`),c;if(i<o){a("getOrRefreshToken",`daily check 500 error (attempt ${i}/${o}) \u2014 retrying in 1s`),await new Promise(l=>setTimeout(l,Q.RETRY_DELAY_MS));continue}throw a("getOrRefreshToken",`daily check failed after ${o} attempts \u2014 propagating`),c}a("getOrRefreshToken",`daily check network error \u2014 using cache: ${c.message}`);break}}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 s=await Y(t);try{await Ft({...s,lastAuthCheckAt:e});}catch(o){a("getOrRefreshToken",`token cache save failed (non-fatal): ${o.message}`);}return a("getOrRefreshToken",`token refreshed, expires=${s.expiresAt}`),s.accessToken}function wr(t,e){let r=e&&e.accessToken?e.accessToken:"";return {endpoint:t.replace(/\/$/,"")+"/flow-langfuse-gateway/v1/traces",authHeader:`Bearer ${r}`}}function Rr(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 K(){let t=[],e=Tt(process.env[g.ANTHROPIC_AUTH_TOKEN]);a("resolveCredentials",e?"credentials resolved from ANTHROPIC_AUTH_TOKEN":"ANTHROPIC_AUTH_TOKEN absent or invalid"),e&&a("resolveCredentials",`clientId=${e.clientId}`,`tenant=${e.tenant}`);let r=e?e.tenant:"",n=process.env[g.FLOW_TELEMETRY]==="true",s=process.env[g.LANGFUSE_BASE_URL],o=process.env[g.LANGFUSE_PUBLIC_KEY],i=process.env[g.LANGFUSE_SECRET_KEY];if(n&&s&&o&&i){let m="",_=r;e&&(m=await nt().catch(()=>null)??e.clientId);let E={user:m??"",tenant:_??"",team:"",project:""};t.push({mode:"direct",...Rr(St(s),o,i),...E}),a("resolveCredentials","direct mode active",`user=${E.user}`,`tenant=${E.tenant}`);}if(!e){if(t.length===0){let m=[];return m.authError=false,m}return t}let c;try{c=await kr(e);}catch(m){if(a("resolveCredentials",`token refresh failed: ${m.message}`,`(tenant=${e.tenant} clientId=${e.clientId})`),t.length>0)return t.authError=true,t;let _=[];return _.authError=true,_}let p={user:yr(c)??e.clientId,tenant:r,team:"",project:""},S=process.env[g.FLOW_TELEMETRY_GATEWAY]??B();return t.push({mode:"gateway",...wr(St(S),{accessToken:c}),...p}),t}function L(t,e){let r=typeof t=="object"?JSON.stringify(t):String(t??"");return r.length>e?r.slice(0,e)+" \u2026[truncated]":r}function ht(t,e=100){return String(t??"").split(`
11
+ `)[0].slice(0,e).trim()}function it(){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 A(t){process.stdout.write(JSON.stringify(t));}var xt=()=>crypto.randomBytes(16).toString("hex"),C=()=>crypto.randomBytes(8).toString("hex");function P(){return String(BigInt(Date.now())*1000000n)}var Fr=/^[0-9a-f-]{1,64}$/i,$r=G.normalize(st.tmpdir())+G.sep;function Dr(t,e){let r=G.resolve(t);if(!r.startsWith(e))throw new Error(`Path traversal detected: ${t}`);return r}function Mt(t){if(!Fr.test(t))throw new Error(`Invalid session ID: ${t}`);return Dr(G.join(st.tmpdir(),`flow-obs-${t}.json`),$r)}function J(t){let e;try{e=Mt(t);}catch{return null}if(!h.existsSync(e))return null;try{return JSON.parse(h.readFileSync(e,"utf8"))}catch{return null}}function X(t,e){h.writeFileSync(Mt(t),JSON.stringify(e),{encoding:"utf8",mode:384});}function Bt(t){try{h.unlinkSync(Mt(t));}catch{}}function Se(t){if(!t||!h.existsSync(t))return null;try{let e=h.readFileSync(t,"utf8").trimEnd().split(`
12
+ `);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 Ht(t){if(!t||!h.existsSync(t))return null;try{let e=h.readFileSync(t,"utf8").trimEnd().split(`
13
+ `),r=[],n=0,s=0,o;for(let i=e.length-1;i>=0;i--)try{let c=JSON.parse(e[i]);if(c.type==="user")break;if(c.type==="assistant"){!o&&c.message?.model&&(o=c.message.model);let p=(c.message?.content??[]).filter(m=>m.type==="text").map(m=>m.text??"").join("");p&&r.unshift(p);let S=c.message?.usage??{};n+=(S.input_tokens??0)+(S.cache_read_input_tokens??0)+(S.cache_creation_input_tokens??0),s+=S.output_tokens??0;}}catch{}return !r.length&&n===0?null:{text:r.join(`
7
14
 
8
- `),inputTokens:n,outputTokens:i}}catch{}return null}var Sr=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=[M.join(me.homedir(),".claude","skills",r,"SKILL.md"),M.join(e??"",".claude","skills",r,"SKILL.md")];for(let i of n)if(R.existsSync(i))try{return R.readFileSync(i,"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 Ar=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||Ar.has(n.tool))?"complete":"prerequisite_required":null}function ft(t,e){if(!t)return null;let r=oe(t),n=[M.join(me.homedir(),".claude","skills",r),M.join(e??"",".claude","skills",r)],i=null;for(let c of n)if(R.existsSync(M.join(c,"SKILL.md"))){i=c;break}if(!i)return null;let s=[];function o(c,l){for(let p of R.readdirSync(c,{withFileTypes:true})){if(Sr.has(p.name)||hr.has(p.name)||Er.has(M.extname(p.name)))continue;let T=l?`${l}/${p.name}`:p.name;p.isDirectory()?o(M.join(c,p.name),T):s.push(T);}}return o(i,""),s.length>0?s:null}function kr(t){try{let e=t.split(".")[1].replace(/-/g,"+").replace(/_/g,"/");return JSON.parse(Buffer.from(e,"base64").toString())}catch{return null}}function wr(t,e,r,n){return new Promise(i=>{let s=new URL(t),o=s.protocol==="https:",c=(o?Je__default.default:Ke__default.default).request({hostname:s.hostname,port:s.port||(o?443:80),path:s.pathname+s.search,method:"POST",headers:{"Content-Type":"application/json","Content-Length":Buffer.byteLength(e),Authorization:`Bearer ${String(r).replace(/[\r\n]/g,"")}`,FlowTenant:String(n).replace(/[\r\n]/g,"")}},l=>{l.resume(),i(l.statusCode??0);});c.on("error",()=>i(0)),c.setTimeout(5e3,()=>{c.destroy(),i(0);}),c.write(e),c.end();})}async function v(t,e={}){try{let r=ut(process.env[_.ANTHROPIC_AUTH_TOKEN]);if(!r)return;let n,i=new Promise((S,m)=>{n=setTimeout(()=>m(new Error("getToken timeout")),4e3),n.unref();}),{accessToken:s}=await Promise.race([X(r),i]);clearTimeout(n);let o=kr(s);if(!o)return;let c=o.tenant||r.tenant,l=JSON.stringify({action:t,booster:St().BOOSTER,metadata:e,success:!0,tenant:c,timestamp:new Date().toISOString(),os:process.platform,user:{email:o.email||"",id:o.sub||"",name:o.name||o.email||""}}),p=lt(St().API_URL),T=await wr(p,l,s,c);a("metrics.logEvent",`action=${t} status=${T}`);}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 ${D()}/settings/api-keys to generate a new API key, then run: flow-ai-obs login`;async function vt(t,e=false){if(e){process.stdout.write(JSON.stringify({decision:"block",reason:Lr})+`
10
- `);return}let n=!!(await x()).authError,i=t.session_id||"unknown",s=t.prompt||"",o=t.cwd||"",c=re(t.transcript_path)||Pt(),l=ie(s),p=l?dt(l,o):null,T=l?ft(l,o):null;Y(i,{traceId:Pt(),spanId:U(),startNs:L(),sessionId:i,prompt:s,cwd:o,traceName:c,transcriptPath:t.transcript_path||"",model:process.env[_.ANTHROPIC_MODEL]||"",toolCalls:[],spans:[],pendingTool:null,slashSkill:l,skillContent:p,skillArtifacts:T}),v("SESSION_STARTED",{traceType:l?"skill":"prompt",slashSkill:l,clientIdExpired:n}),a("UserPromptSubmit",`sid=${i}`,`traceName=${c}`,`slashSkill=${l}`),A(t);}async function ce(t){let e=t.session_id||"unknown",r=t.tool_name||"unknown",n=t.tool_input||{},i=B(e);i&&(i.pendingTool={name:r,inputStr:w(n,k.TOOL_INPUT),startNs:L()},Y(e,i)),a("PreToolUse",`sid=${e}`,`tool=${r}`,`stateFound=${!!i}`),A(t);}var Rr={name:Tt.SCOPE_NAME,version:Tt.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 C(...t){return t.filter(e=>e!==null)}function le(t,e){return {resourceSpans:[{resource:{attributes:t},scopeSpans:[{scope:Rr,spans:Array.isArray(e)?e:[e]}]}]}}var ue=M.join(me.tmpdir(),"flow-obs-requests.ndjson");function pe(t,e,r,n,i){if(process.env[_.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:i}});try{R.writeFileSync(ue,s+`
11
- `,{flag:"a",encoding:"utf8",mode:384}),a("sendTraces:dump",`request appendada em ${ue}`);}catch(o){a("sendTraces:dump",`falha ao salvar: ${o.message}`);}}function vr(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 i=t._isSSL?Je__default.default:Ke__default.default;t.headers=Object.assign({},t.headers,{Connection:"close"});let s=i.request(t,o=>{let c=[];o.on("data",l=>c.push(l)),o.on("end",()=>r({statusCode:o.statusCode??0,body:c.join("")}));});s.setTimeout(1e4,()=>{s.destroy(new Error("Request timeout"));}),s.on("error",o=>n(new Error(`Network error: ${o.message}`))),e&&s.write(e),s.end();})}async function fe(t,e){let r;try{r=vr(t);}catch{return false}let n=r.protocol==="https:";try{let i={};e&&(i.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:i,_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),i=new URL(e),s=i.protocol==="https:",o=String(r).replace(/[\r\n]/g,""),c={"Content-Type":"application/json",Authorization:o,"Content-Length":Buffer.byteLength(n)};a("sendTraces:request",`POST ${e}`),a("sendTraces:request",`headers=${JSON.stringify({...c,Authorization:o.slice(0,20)+"\u2026"})}`),a("sendTraces:request",`body=${n.slice(0,500)}${n.length>500?"\u2026":""}`);try{let l=await de({hostname:i.hostname,port:i.port||(s?443:80),path:i.pathname,method:"POST",headers:c,_isSSL:s},n);return a("sendTraces:response",`status=${l.statusCode}`),pe(e,c,n,l.statusCode,l.body),l.statusCode}catch(l){return a("sendTraces:error",l.message),pe(e,c,n,0,l.message),0}}function Cr(){let t=parseInt(process.env[_.BUFFER_TTL_DAYS]??"",10);return (Number.isFinite(t)?Math.max(O.MIN_TTL_DAYS,Math.min(O.MAX_TTL_DAYS,t)):O.DEFAULT_TTL_DAYS)*24*60*60*1e3}function $r(){let t=parseInt(process.env[_.BUFFER_MAX_FILES]??"",10);return Number.isFinite(t)?Math.max(O.MIN_MAX_FILES,Math.min(O.MAX_MAX_FILES,t)):O.DEFAULT_MAX_FILES}function ge(t){if(/[/\\]/.test(t))throw new Error(`Invalid buffer fileId: ${t}`);return M__default.default.join(me__default.default.tmpdir(),`${O.FILE_PREFIX}${t}.json`)}function $t(){let t=me__default.default.tmpdir(),e;try{e=R__default.default.readdirSync(t);}catch{return []}return e.filter(r=>r.startsWith(O.FILE_PREFIX)&&r.endsWith(".json")).map(r=>{let n=M__default.default.join(t,r),i=0;try{i=R__default.default.statSync(n).mtimeMs;}catch{}return {full:n,mtime:i}}).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 o of s)try{R__default.default.unlinkSync(o);}catch{}}let n=`${Date.now()}-${Math.random().toString(36).slice(2,8)}`,i={fileId:n,bufferedAt:Date.now(),payload:t};return R__default.default.writeFileSync(ge(n),JSON.stringify(i),{encoding:"utf8",mode:384}),a("buffer",`saved fileId=${n}`),n}catch(e){return a("buffer",`saveToBuffer failed: ${e.message}`),null}}function _e(t){let e=$t(),r=t,n=[];for(let i of e){if(n.length>=r)break;try{let s=R__default.default.readFileSync(i,"utf8"),o=JSON.parse(s);o&&o.fileId&&o.payload&&n.push(o);}catch{a("buffer",`skipping malformed file: ${i}`);}}return n}function Te(t){try{R__default.default.unlinkSync(ge(t)),a("buffer",`deleted fileId=${t}`);}catch{}}function Se(){let t=Date.now()-Cr();for(let e of $t())try{let{mtimeMs:r}=R__default.default.statSync(e);r<t&&(R__default.default.unlinkSync(e),a("buffer",`evicted stale: ${M__default.default.basename(e)}`));}catch{}}async function Fr(t){Se();let e=_e(O.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?(Te(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 x();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 o=await fe(s.endpoint,s.authHeader);return {creds:s,healthy:o}})),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:o})=>{if(s.mode==="gateway"){if(!o)return a("postToLangfuse","gateway health check failed \u2014 buffering trace"),Z(t),0;let l=await mt(t,s.endpoint,s.authHeader);return (l===0||l>=500)&&(a("postToLangfuse",`gateway send failed (status ${l}) \u2014 buffering trace`),Z(t)),l}let c=await mt(t,s.endpoint,s.authHeader);return (c===0||c>=500)&&(a("postToLangfuse",`direct endpoint unavailable (status ${c}) \u2014 buffering trace`),Z(t)),c}))).find(s=>s!==0)??0}var y="[REDACTED]",Dr="[REDACTED-EMAIL]",Mr="[REDACTED-CPF]",xr="[REDACTED-CNPJ]",he="[REDACTED-PHONE]",Br=[{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:()=>Mr},{re:/\b\d{2}\.\d{3}\.\d{3}\/\d{4}-\d{2}\b/g,replace:()=>xr},{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 I(t){if(t==null)return "";let e=typeof t=="string"?t:JSON.stringify(t);return Br.reduce((r,{re:n,replace:i})=>r.replace(n,i),e)}async function Ae(t){let e=t.session_id||"unknown",r=t.tool_name||"unknown",n=t.tool_input||{},i=t.tool_response,s=i!==null&&typeof i=="object"?i.output??JSON.stringify(i):i??"",o=B(e);if(!o){A(t);return}let c=L(),l=o.pendingTool,p=l?.name===r,T=p?l.startNs:String(BigInt(c)-200000000n),S=p?l.inputStr:w(n,k.TOOL_INPUT),m=S,g=null;if(r==="Skill"){let st=typeof n=="object"&&n!==null?n.skill||n.name||n.skillName||n.commandName||String(Object.values(n)[0]??""):String(n);g=st?String(st).trim():null;let P=g?dt(g,o.cwd):null;P&&(m=P,o.skillContent||(o.skillContent=P),o.skillArtifacts||(o.skillArtifacts=ft(g,o.cwd))),g&&!o.slashSkill&&(o.slashSkill=g),a("PostToolUse","Skill tool detected",`skillName=${g}`,`contentFound=${!!P}`);}let E=I(w(s,k.TOOL_OUTPUT)),h=/\b(error|exception|failed|failure|traceback|errno)\b/i.test(E.slice(0,500)),Q=h?"ERROR":"DEFAULT",V=U(),tt=Math.round(Number(BigInt(c)-BigInt(T))/1e6),rt={Agent:"AGENT",Task:"AGENT"}[r]??"TOOL",nt=r==="Skill"&&g?g:pt(S,60);o.toolCalls.push({tool:r,brief:nt,error:h,durationMs:tt});let G=o.spans;G.push({traceId:o.traceId,spanId:V,parentSpanId:o.spanId,name:r,kind:3,startTimeUnixNano:T,endTimeUnixNano:c,attributes:C(u(f.OBS_NAME,r),u(f.OBS_TYPE,rt),u(f.OBS_LEVEL,Q),u(f.OBS_INPUT,I(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}}),o.pendingTool=null,Y(e,o),h&&v("TOOL_ERROR",{toolName:r}),a("PostToolUse",`sid=${e}`,`tool=${r}`,`error=${h}`,`durationMs=${tt}`,`totalSpans=${G.length}`),A(t);}var ye={"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 Oe(t,e,r){let n=Object.keys(ye).find(o=>(t??"").toLowerCase().includes(o));if(!n)return;let i=ye[n],s=(e*i.input+r*i.output)/1e6;return Math.round(s*1e6)/1e6}async function ke(t){let e=t.session_id||"unknown",r=t.stop_reason||"end_turn",n=B(e);if(!n){A(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 i=L(),s=await zt(),o=n.toolCalls,c=n.spans;if(n.slashSkill&&!o.some(d=>d.tool==="Skill")){let d=U(),N=n.skillContent?n.skillContent:JSON.stringify({skill:n.slashSkill});o.push({tool:"Skill",brief:n.slashSkill,error:false,durationMs:0,synthetic:true}),c.push({traceId:n.traceId,spanId:d,parentSpanId:n.spanId,name:"Skill",kind:3,startTimeUnixNano:n.startNs,endTimeUnixNano:n.startNs,attributes:C(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 l=t.transcript_path||n.transcriptPath||"",p=Ut(l);if(l&&(o.some(d=>d.tool==="Skill"&&!d.synthetic)||!!n.slashSkill)&&!p?.text){await new Promise(N=>setTimeout(N,500));let d=Ut(l);d?.text&&(p=d);}a("Stop",`transcriptPath=${l||"(empty)"}`,`assistantOut=${p?`text=${p.text.length}chars`:"null"}`);let S=o.length,m=o.filter(d=>d.error).length,g=I(p?.text?w(p.text,k.TRACE_OUTPUT):S===0?"No tools used":o.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,Q=o.map((d,N)=>`${N+1}. ${d.tool}${d.brief?` \u2192 ${d.brief}`:""}${d.error?" [ERROR]":""} (${d.durationMs}ms)`),V=!!(n.slashSkill||o.some(d=>d.tool==="Skill")),tt=o.some(d=>d.tool==="Agent");if(!V&&!tt){a("Stop",`sid=${e}`,"skipping trace \u2014 no Skill or Agent calls found"),v("TRACE_SKIPPED",{reason:"no_skill_or_agent"}),bt(e),A(t);return}let et=V?"skill":"agent",rt=Math.round(Number(BigInt(i)-BigInt(n.startNs))/1e6),nt=Oe(n.model,E,h),F=ae(n);F==="prerequisite_required"&&p?.text&&(F="complete"),F==="prerequisite_required"&&(c.push({traceId:n.traceId,spanId:U(),parentSpanId:n.spanId,name:"prerequisite-check",kind:3,startTimeUnixNano:n.startNs,endTimeUnixNano:i,attributes:C(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(!(!V||!n.prompt)){if(n.slashSkill){let d=n.prompt.replace(new RegExp(`^\\/${n.slashSkill}\\s*`,"i"),"").trim();return d?w(I(d),k.USER_INSTRUCTION):void 0}return w(I(n.prompt),k.USER_INSTRUCTION)||void 0}})(),st=JSON.stringify({trace_type:et,...F!==null&&{execution_status:F},...n.slashSkill?{skill_name:n.slashSkill}:{},...n.skillArtifacts?.length&&{skill_artifacts:n.skillArtifacts},...G!==void 0&&{user_instruction:G},latency_ms:rt,...E&&{tokens_input:E},...h&&{tokens_output:h},cost_usd:nt,...n.model?{model:n.model}:{},toolCount:S,errorCount:m,stopReason:r,sessionId:n.sessionId,tools:Q.length?Q:void 0}),P=I(w(n.prompt,k.TRACE_INPUT)),we=C(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,st),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(S)),u("claude.error_count",String(m)),u("claude.session_id",n.sessionId),u("flow.trace_type",et),{key:f.TRACE_TAGS,value:{arrayValue:{values:[{stringValue:et}]}}}),Le={traceId:n.traceId,spanId:n.spanId,name:n.traceName,kind:1,startTimeUnixNano:n.startNs,endTimeUnixNano:i,attributes:we,status:{code:m>0?2:1}},Re=C(u("service.name",process.env.LANGFUSE_PROJECT_NAME||"claude-code"),u("deployment.environment",process.env.LANGFUSE_ENVIRONMENT||"default")),Ft=[...c,Le];a("Stop",`sid=${e}`,`totalTools=${S}`,`errorTools=${m}`,`spans=${Ft.length}`,`inputTokens=${E}`,`outputTokens=${h}`,`traceOutput="${pt(g,80)}"`);let Ie=await Ee(le(Re,Ft));a("Stop",`POST status=${Ie}`,`traceId=${n.traceId}`),v("TRACE_SENT",{latencyMs:rt,totalTools:S,errorTools:m,inputTokens:E,outputTokens:h,costUsd:nt}),bt(e),A(t);}var $=class{static async userPromptSubmit(){let e=await z(),r;try{r=await x();}catch{A(e);return}r.authError?await vt(e,true):r.length>0?await vt(e):A(e);}static async preToolUse(){let e=await z();await ce(e);}static async postToolUse(){let e=await z();await Ae(e);}static async stop(){let e=await z();await ke(e);}};async function Yr(){let t=process.argv[2];switch(t){case "UserPromptSubmit":await $.userPromptSubmit();break;case "PreToolUse":await $.preToolUse();break;case "PostToolUse":await $.postToolUse();break;case "Stop":await $.stop();break;default:process.stderr.write(`[flow-obs] unknown event: ${t}
15
- `),process.stdin.on("data",e=>process.stdout.write(e));}}Yr().catch(t=>{process.stderr.write(`[flow-obs] fatal: ${t.message}
15
+ `),inputTokens:n,outputTokens:s,model:o}}catch{}return null}var Hr=new Set([".venv","__pycache__",".git","node_modules"]),Wr=new Set([".pyc",".pyo"]),Gr=new Set(["SKILL.md",".DS_Store",".gitignore"]);function ye(t){return t.replace(":","/")}function yt(t,e){if(!t)return null;let r=ye(t),n=[G.join(st.homedir(),".claude","skills",r,"SKILL.md"),G.join(e??"",".claude","skills",r,"SKILL.md")];for(let s of n)if(h.existsSync(s))try{return h.readFileSync(s,"utf8")}catch{}return null}function Ae(t){return t.split(`
16
+ `)[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 Oe(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 At(t,e){if(!t)return null;let r=ye(t),n=[G.join(st.homedir(),".claude","skills",r),G.join(e??"",".claude","skills",r)],s=null;for(let c of n)if(h.existsSync(G.join(c,"SKILL.md"))){s=c;break}if(!s)return null;let o=[];function i(c,l){for(let p of h.readdirSync(c,{withFileTypes:true})){if(Hr.has(p.name)||Gr.has(p.name)||Wr.has(G.extname(p.name)))continue;let S=l?`${l}/${p.name}`:p.name;p.isDirectory()?i(G.join(c,p.name),S):o.push(S);}}return i(s,""),o.length>0?o:null}T();T();function Kr(t){try{let e=t.split(".")[1].replace(/-/g,"+").replace(/_/g,"/");return JSON.parse(Buffer.from(e,"base64").toString())}catch{return null}}function Jr(t,e,r,n){return new Promise(s=>{let o=new URL(t),i=o.protocol==="https:",c=(i?cr__default.default:lr__default.default).request({hostname:o.hostname,port:o.port||(i?443:80),path:o.pathname+o.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,"")}},l=>{l.resume(),s(l.statusCode??0);});c.on("error",()=>s(0)),c.setTimeout(5e3,()=>{c.destroy(),s(0);}),c.write(e),c.end();})}async function F(t,e={}){try{let r=Tt(process.env[g.ANTHROPIC_AUTH_TOKEN]);if(!r)return;let n,s=new Promise((m,_)=>{n=setTimeout(()=>_(new Error("getToken timeout")),4e3),n.unref();}),{accessToken:o}=await Promise.race([Y(r),s]);clearTimeout(n);let i=Kr(o);if(!i)return;let c=i.tenant||r.tenant,l=JSON.stringify({action:t,booster:Lt().BOOSTER,metadata:e,success:!0,tenant:c,timestamp:new Date().toISOString(),os:process.platform,user:{email:i.email||"",id:i.sub||"",name:i.name||i.email||""}}),p=St(Lt().API_URL),S=await Jr(p,l,o,c);a("metrics.logEvent",`action=${t} status=${S}`);}catch(r){a("metrics.logEvent",`silenced error: ${r.message}`);}}var Xr=`\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 Wt(t,e=false){if(e){process.stdout.write(JSON.stringify({decision:"block",reason:Xr})+`
17
+ `);return}let n=!!(await K()).authError,s=t.session_id||"unknown",o=t.prompt||"",i=t.cwd||"",c=Se(t.transcript_path)||xt(),l=Ae(o),p=l?yt(l,i):null,S=l?At(l,i):null;X(s,{traceId:xt(),spanId:C(),startNs:P(),sessionId:s,prompt:o,cwd:i,traceName:c,transcriptPath:t.transcript_path||"",toolCalls:[],spans:[],pendingTool:null,slashSkill:l,skillContent:p,skillArtifacts:S}),F("SESSION_STARTED",{traceType:l?"skill":"prompt",slashSkill:l,clientIdExpired:n}),a("UserPromptSubmit",`sid=${s}`,`traceName=${c}`,`slashSkill=${l}`),A(t);}T();async function ke(t){let e=t.session_id||"unknown",r=t.tool_name||"unknown",n=t.tool_input||{},s=J(e);s&&(s.pendingTool={name:r,inputStr:L(n,R.TOOL_INPUT),startNs:P()},X(e,s)),a("PreToolUse",`sid=${e}`,`tool=${r}`,`stateFound=${!!s}`),A(t);}T();var qr={name:Rt.SCOPE_NAME,version:Rt.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 u(t,e){return e==null||e===""?null:{key:t,value:{stringValue:String(e)}}}function $(...t){return t.filter(e=>e!==null)}function we(t,e){return {resourceSpans:[{resource:{attributes:t},scopeSpans:[{scope:qr,spans:Array.isArray(e)?e:[e]}]}]}}T();var Re=G.join(st.tmpdir(),"flow-obs-requests.ndjson");function Le(t,e,r,n,s){if(process.env[g.FLOW_OBS_DEBUG]!=="1")return;let o=JSON.stringify({ts:new Date().toISOString(),request:{method:"POST",url:t,headers:e,body:JSON.parse(r)},response:{status:n,body:s}});try{h.writeFileSync(Re,o+`
18
+ `,{flag:"a",encoding:"utf8",mode:384}),a("sendTraces:dump",`request appendada em ${Re}`);}catch(i){a("sendTraces:dump",`falha ao salvar: ${i.message}`);}}function rn(t){let e=new URL(t),r=new URL(H().GATEWAY_HEALTH);return r.hostname=e.hostname,r.port=e.port,r.protocol=e.protocol,r}function Ie(t,e){return new Promise((r,n)=>{let s=t._isSSL?cr__default.default:lr__default.default;t.headers=Object.assign({},t.headers,{Connection:"close"});let o=s.request(t,i=>{let c=[];i.on("data",l=>c.push(l)),i.on("end",()=>r({statusCode:i.statusCode??0,body:c.join("")}));});o.setTimeout(1e4,()=>{o.destroy(new Error("Request timeout"));}),o.on("error",i=>n(new Error(`Network error: ${i.message}`))),e&&o.write(e),o.end();})}async function Pe(t,e){let r;try{r=rn(t);}catch{return false}let n=r.protocol==="https:";try{let s={};e&&(s.Authorization=String(e).replace(/[\r\n]/g,""));let o=await Ie({hostname:r.hostname,port:r.port||(n?443:80),path:r.pathname,method:"GET",headers:s,_isSSL:n},null);return a("checkHealth",`url=${r.href} status=${o.statusCode}`),o.statusCode>=200&&o.statusCode<300}catch{return false}}async function Ot(t,e,r){let n=JSON.stringify(t),s=new URL(e),o=s.protocol==="https:",i=String(r).replace(/[\r\n]/g,""),c={"Content-Type":"application/json",Authorization:i,"Content-Length":Buffer.byteLength(n)};a("sendTraces:request",`POST ${e}`),a("sendTraces:request",`headers=${JSON.stringify({...c,Authorization:i.slice(0,20)+"\u2026"})}`),a("sendTraces:request",`body=${n.slice(0,500)}${n.length>500?"\u2026":""}`);try{let l=await Ie({hostname:s.hostname,port:s.port||(o?443:80),path:s.pathname,method:"POST",headers:c,_isSSL:o},n);return a("sendTraces:response",`status=${l.statusCode}`),Le(e,c,n,l.statusCode,l.body),l.statusCode}catch(l){return a("sendTraces:error",l.message),Le(e,c,n,0,l.message),0}}T();function nn(){let t=parseInt(process.env[g.BUFFER_TTL_DAYS]??"",10);return (Number.isFinite(t)?Math.max(k.MIN_TTL_DAYS,Math.min(k.MAX_TTL_DAYS,t)):k.DEFAULT_TTL_DAYS)*24*60*60*1e3}function sn(){let t=parseInt(process.env[g.BUFFER_MAX_FILES]??"",10);return Number.isFinite(t)?Math.max(k.MIN_MAX_FILES,Math.min(k.MAX_MAX_FILES,t)):k.DEFAULT_MAX_FILES}function be(t){if(/[/\\]/.test(t))throw new Error(`Invalid buffer fileId: ${t}`);return G__namespace.default.join(st__namespace.default.tmpdir(),`${k.FILE_PREFIX}${t}.json`)}function Yt(){let t=st__namespace.default.tmpdir(),e;try{e=h__namespace.default.readdirSync(t);}catch{return []}return e.filter(r=>r.startsWith(k.FILE_PREFIX)&&r.endsWith(".json")).map(r=>{let n=G__namespace.default.join(t,r),s=0;try{s=h__namespace.default.statSync(n).mtimeMs;}catch{}return {full:n,mtime:s}}).sort((r,n)=>r.mtime-n.mtime).map(r=>r.full)}function at(t){try{let e=sn(),r=Yt();if(r.length>=e){let o=r.slice(0,r.length-e+1);for(let i of o)try{h__namespace.default.unlinkSync(i);}catch{}}let n=`${Date.now()}-${Math.random().toString(36).slice(2,8)}`,s={fileId:n,bufferedAt:Date.now(),payload:t};return h__namespace.default.writeFileSync(be(n),JSON.stringify(s),{encoding:"utf8",mode:384}),a("buffer",`saved fileId=${n}`),n}catch(e){return a("buffer",`saveToBuffer failed: ${e.message}`),null}}function Ne(t){let e=Yt(),r=t!=null&&t>0?t:e.length,n=[];for(let s of e){if(n.length>=r)break;try{let o=h__namespace.default.readFileSync(s,"utf8"),i=JSON.parse(o);i&&i.fileId&&i.payload&&n.push(i);}catch{a("buffer",`skipping malformed file: ${s}`);}}return n}function Ue(t){try{h__namespace.default.unlinkSync(be(t)),a("buffer",`deleted fileId=${t}`);}catch{}}function Ce(){let t=Date.now()-nn();for(let e of Yt())try{let{mtimeMs:r}=h__namespace.default.statSync(e);r<t&&(h__namespace.default.unlinkSync(e),a("buffer",`evicted stale: ${G__namespace.default.basename(e)}`));}catch{}}T();async function on(t){Ce();let e=Ne(k.REPLAY_BATCH_SIZE);e.length&&(a("replayBufferedTraces",`replaying ${e.length} buffered trace(s)`),await Promise.allSettled(e.map(async r=>{try{let n=await Ot(r.payload,t.endpoint,t.authHeader);n>=200&&n<300?(Ue(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 Fe(t){let e=await K();if(!e.length)return e.authError&&(a("postToLangfuse","auth refresh failed \u2014 buffering trace"),at(t)),0;let r=await Promise.all(e.map(async o=>{if(o.mode!=="gateway")return {creds:o,healthy:true};let i=await Pe(o.endpoint,o.authHeader);return {creds:o,healthy:i}})),n=r.find(o=>o.creds.mode==="gateway"&&o.healthy)?.creds??r.find(o=>o.creds.mode==="direct")?.creds;return n&&await on(n),(await Promise.all(r.map(async({creds:o,healthy:i})=>{if(o.mode==="gateway"){if(!i)return a("postToLangfuse","gateway health check failed \u2014 buffering trace"),at(t),0;let l=await Ot(t,o.endpoint,o.authHeader);return (l===0||l>=500)&&(a("postToLangfuse",`gateway send failed (status ${l}) \u2014 buffering trace`),at(t)),l}let c=await Ot(t,o.endpoint,o.authHeader);return (c===0||c>=500)&&(a("postToLangfuse",`direct endpoint unavailable (status ${c}) \u2014 buffering trace`),at(t)),c}))).find(o=>o!==0)??0}T();var O="[REDACTED]",an="[REDACTED-EMAIL]",cn="[REDACTED-CPF]",ln="[REDACTED-CNPJ]",$e="[REDACTED-PHONE]",un=[{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,r)=>`${e}
19
+ ${O}
20
+ ${r}`},{re:/\b(AKIA[0-9A-Z]{16})\b/g,replace:()=>`AKIA${O}`},{re:/(aws_secret_access_key\s*[=:]\s*)([A-Za-z0-9/+]{40})/gi,replace:(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,r)=>`${e}${r}${O}${r}`},{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:()=>an},{re:/\b\d{3}\.\d{3}\.\d{3}-\d{2}\b/g,replace:()=>cn},{re:/\b\d{2}\.\d{3}\.\d{3}\/\d{4}-\d{2}\b/g,replace:()=>ln},{re:/\(\d{2}\)\s?\d{4,5}[-\s]?\d{4}/g,replace:()=>$e},{re:/\+55[\s-]?\d{2}[\s-]?\d{4,5}[-\s]?\d{4}/g,replace:()=>$e}];function b(t){if(t==null)return "";let e=typeof t=="string"?t:JSON.stringify(t);return un.reduce((r,{re:n,replace:s})=>r.replace(n,s),e)}async function De(t){let e=t.session_id||"unknown",r=t.tool_name||"unknown",n=t.tool_input||{},s=t.tool_response,o=s!==null&&typeof s=="object"?s.output??JSON.stringify(s):s??"",i=J(e);if(!i){A(t);return}let c=P(),l=i.pendingTool,p=l?.name===r,S=p?l.startNs:String(BigInt(c)-200000000n),m=p?l.inputStr:L(n,R.TOOL_INPUT),_=m,E=null;if(r==="Skill"){let Z=typeof n=="object"&&n!==null?n.skill||n.name||n.skillName||n.commandName||String(Object.values(n)[0]??""):String(n);E=Z?String(Z).trim():null;let M=E?yt(E,i.cwd):null;M&&(_=M,i.skillContent||(i.skillContent=M),i.skillArtifacts||(i.skillArtifacts=At(E,i.cwd))),E&&!i.slashSkill&&(i.slashSkill=E),a("PostToolUse","Skill tool detected",`skillName=${E}`,`contentFound=${!!M}`);}let w=b(L(o,R.TOOL_OUTPUT)),y=/\b(error|exception|failed|failure|traceback|errno)\b/i.test(w.slice(0,500)),ct=y?"ERROR":"DEFAULT",z=C(),lt=Math.round(Number(BigInt(c)-BigInt(S))/1e6),pt={Agent:"AGENT",Task:"AGENT"}[r]??"TOOL",x=r==="Skill"&&E?E:ht(m,60);i.toolCalls.push({tool:r,brief:x,error:y,durationMs:lt});let I=i.spans;I.push({traceId:i.traceId,spanId:z,parentSpanId:i.spanId,name:r,kind:3,startTimeUnixNano:S,endTimeUnixNano:c,attributes:$(u(d.OBS_NAME,r),u(d.OBS_TYPE,pt),u(d.OBS_LEVEL,ct),u(d.OBS_INPUT,b(_)),u(d.OBS_OUTPUT,w),u("tool.name",r),u("tool.error",String(y)),r==="Skill"&&E?u("skill.name",E):null,r==="Skill"?u("skill.invocation","slash-command"):null),status:{code:y?2:1}}),i.pendingTool=null,X(e,i),y&&F("TOOL_ERROR",{toolName:r}),a("PostToolUse",`sid=${e}`,`tool=${r}`,`error=${y}`,`durationMs=${lt}`,`totalSpans=${I.length}`),A(t);}var xe={"claude-opus-5":{input:5,output:25},"claude-sonnet-5":{input:2,output:10},"claude-fable-5":{input:10,output:50},"claude-opus-4-6":{input:5,output:25},"claude-opus-4-5":{input:5,output:25},"claude-sonnet-4-6":{input:3,output:15},"claude-sonnet-4-5":{input:3,output:15},"claude-haiku-4-5":{input:1,output:5},"claude-4-6-opus":{input:5,output:25},"claude-4-6-sonnet":{input:3,output:15},"claude-4-5-opus":{input:5,output:25},"claude-4-5-sonnet":{input:3,output:15},"claude-4-5-haiku":{input:1,output:5},"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 Me(t,e,r){let n=Object.keys(xe).find(i=>(t??"").toLowerCase().includes(i));if(!n)return;let s=xe[n],o=(e*s.input+r*s.output)/1e6;return Math.round(o*1e6)/1e6}T();async function Be(t){let e=t.session_id||"unknown",r=t.stop_reason||"end_turn",n=J(e);if(!n){A(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 s=P(),o=await de(),i=n.toolCalls,c=n.spans;if(n.slashSkill&&!i.some(f=>f.tool==="Skill")){let f=C(),N=n.skillContent?n.skillContent:JSON.stringify({skill:n.slashSkill});i.push({tool:"Skill",brief:n.slashSkill,error:false,durationMs:0,synthetic:true}),c.push({traceId:n.traceId,spanId:f,parentSpanId:n.spanId,name:"Skill",kind:3,startTimeUnixNano:n.startNs,endTimeUnixNano:n.startNs,attributes:$(u(d.OBS_NAME,"Skill"),u(d.OBS_TYPE,"TOOL"),u(d.OBS_LEVEL,"DEFAULT"),u(d.OBS_INPUT,N),u(d.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 l=t.transcript_path||n.transcriptPath||"",p=Ht(l);if(l&&(i.some(f=>f.tool==="Skill"&&!f.synthetic)||!!n.slashSkill)&&!p?.text){await new Promise(N=>setTimeout(N,500));let f=Ht(l);f?.text&&(p=f);}a("Stop",`transcriptPath=${l||"(empty)"}`,`assistantOut=${p?`text=${p.text.length}chars`:"null"}`);let m=i.length,_=i.filter(f=>f.error).length,E=b(p?.text?L(p.text,R.TRACE_OUTPUT):m===0?"No tools used":i.map((f,N)=>`${N+1}. ${f.tool}${f.brief?` \u2192 ${f.brief}`:""}${f.error?" [ERROR]":""}`).join(`
21
+ `)),w=p?.inputTokens??0,y=p?.outputTokens??0,ct=i.map((f,N)=>`${N+1}. ${f.tool}${f.brief?` \u2192 ${f.brief}`:""}${f.error?" [ERROR]":""} (${f.durationMs}ms)`),z=!!(n.slashSkill||i.some(f=>f.tool==="Skill")),lt=i.some(f=>f.tool==="Agent");if(!z&&!lt){a("Stop",`sid=${e}`,"skipping trace \u2014 no Skill or Agent calls found"),F("TRACE_SKIPPED",{reason:"no_skill_or_agent"}),Bt(e),A(t);return}let ut=z?"skill":"agent",pt=Math.round(Number(BigInt(s)-BigInt(n.startNs))/1e6),x=p?.model||"",kt=Me(x,w,y),I=Oe(n);I==="prerequisite_required"&&p?.text&&(I="complete"),I==="prerequisite_required"&&(c.push({traceId:n.traceId,spanId:C(),parentSpanId:n.spanId,name:"prerequisite-check",kind:3,startTimeUnixNano:n.startNs,endTimeUnixNano:s,attributes:$(u(d.OBS_NAME,"prerequisite-check"),u(d.OBS_TYPE,"EVENT"),u(d.OBS_LEVEL,"WARNING"),u(d.OBS_OUTPUT,E),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 Z=(()=>{if(!(!z||!n.prompt)){if(n.slashSkill){let f=n.prompt.replace(new RegExp(`^\\/${n.slashSkill}\\s*`,"i"),"").trim();return f?L(b(f),R.USER_INSTRUCTION):void 0}return L(b(n.prompt),R.USER_INSTRUCTION)||void 0}})(),M=JSON.stringify({trace_type:ut,...I!==null&&{execution_status:I},...n.slashSkill?{skill_name:n.slashSkill}:{},...n.skillArtifacts?.length&&{skill_artifacts:n.skillArtifacts},...Z!==void 0&&{user_instruction:Z},latency_ms:pt,...w&&{tokens_input:w},...y&&{tokens_output:y},cost_usd:kt,...x?{model:x}:{},toolCount:m,errorCount:_,stopReason:r,sessionId:n.sessionId,tools:ct.length?ct:void 0}),Vt=b(L(n.prompt,R.TRACE_INPUT)),He=$(u(d.TRACE_NAME,n.traceName),u(d.TRACE_INPUT,Vt),u(d.TRACE_OUTPUT,E),u(d.OBS_INPUT,Vt),u(d.OBS_OUTPUT,E),u(d.TRACE_METADATA,M),u(d.SESSION_ID,n.sessionId),u(d.USER_ID,o.user),u(d.OBS_TYPE,"GENERATION"),u(d.MODEL,x),w?u(d.INPUT_TOKENS,w):null,y?u(d.OUTPUT_TOKENS,y):null,u("claude.stop_reason",r),u("claude.tool_count",String(m)),u("claude.error_count",String(_)),u("claude.session_id",n.sessionId),u("flow.trace_type",ut),{key:d.TRACE_TAGS,value:{arrayValue:{values:[{stringValue:ut}]}}}),We={traceId:n.traceId,spanId:n.spanId,name:n.traceName,kind:1,startTimeUnixNano:n.startNs,endTimeUnixNano:s,attributes:He,status:{code:_>0?2:1}},Ge=$(u("service.name",process.env.LANGFUSE_PROJECT_NAME||"claude-code"),u("deployment.environment",process.env.LANGFUSE_ENVIRONMENT||"default")),jt=[...c,We];a("Stop",`sid=${e}`,`totalTools=${m}`,`errorTools=${_}`,`spans=${jt.length}`,`inputTokens=${w}`,`outputTokens=${y}`,`traceOutput="${ht(E,80)}"`);let Ye=await Fe(we(Ge,jt));a("Stop",`POST status=${Ye}`,`traceId=${n.traceId}`),F("TRACE_SENT",{latencyMs:pt,totalTools:m,errorTools:_,inputTokens:w,outputTokens:y,costUsd:kt}),Bt(e),A(t);}var D=class{static async userPromptSubmit(){let e=await it(),r;try{r=await K();}catch{A(e);return}r.authError?await Wt(e,true):r.length>0?await Wt(e):A(e);}static async preToolUse(){let e=await it();await ke(e);}static async postToolUse(){let e=await it();await De(e);}static async stop(){let e=await it();await Be(e);}};async function pn(){let t=process.argv[2];switch(t){case "UserPromptSubmit":await D.userPromptSubmit();break;case "PreToolUse":await D.preToolUse();break;case "PostToolUse":await D.postToolUse();break;case "Stop":await D.stop();break;default:process.stderr.write(`[flow-obs] unknown event: ${t}
22
+ `),process.stdin.on("data",e=>process.stdout.write(e));}}pn().catch(t=>{process.stderr.write(`[flow-obs] fatal: ${t.message}
16
23
  `),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'),p=require('os'),dt=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 dt__default=/*#__PURE__*/_interopDefault(dt);var I=Object.defineProperty;var Le=Object.getOwnPropertyDescriptor;var ke=Object.getOwnPropertyNames;var Pe=Object.prototype.hasOwnProperty;var A=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,n)=>(typeof require<"u"?require:t)[n]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var R=(e,t,n)=>()=>{if(n)throw n[0];try{return e&&(t=e(e=0)),t}catch(r){throw n=[r],r}};var Ie=(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});},Ne=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of ke(t))!Pe.call(e,s)&&s!==n&&I(e,s,{get:()=>t[s],enumerable:!(r=Le(t,s))||r.enumerable});return e};var Ce=e=>Ne(I({},"__esModule",{value:true}),e);var K={};L(K,{AUTH_ENGINE:()=>C,BUFFER:()=>Me,CONFIG_DIR_NAME:()=>y,CONFIG_FILE_NAME:()=>T,DEBUG_LOG_FILENAME:()=>F,ENV:()=>u,FEATURES:()=>De,FLOW_URLS:()=>be,HOOK_TIMEOUTS:()=>b,INSTALLER:()=>U,NATIVE_OTEL:()=>N,OTLP:()=>Fe,STATE_FILE_PREFIX:()=>Ve,TRACE_LIMITS:()=>xe,VAULT:()=>E,getFlowBaseUrl:()=>h,getFlowUrls:()=>k,getLlmProxy:()=>$e,getMetrics:()=>He});function h(){let e=process.env.FLOW_BASE_URL;return e&&e.trim()?e.trim():Ue}function k(){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 $e(){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 Ue,be,E,y,T,Fe,N,u,De,C,U,b,Me,F,xe,Ve,l=R(()=>{"use strict";Ue="https://flow.ciandt.com";be=k(),E={SERVICE:"flow-plugins-cli",ACCOUNT_CREDS:"credentials",ACCOUNT_TOKEN:"token-cache"},y="FLOW-nodejs",T="config.json",Fe={SCOPE_NAME:"flow-ai-obs",SCOPE_VERSION:"0.1.0"};N={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"},De={KEYCHAIN_ENABLED:!1},C={REQUEST_TIMEOUT_MS:1e4,MAX_RETRY_ATTEMPTS:3,RETRY_DELAY_MS:1e3},U={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},Me={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},F="flow-ai-obs-debug.log",xe={TOOL_INPUT:2e4,TOOL_OUTPUT:2e4,TRACE_OUTPUT:2e4,USER_INSTRUCTION:1e4,TRACE_INPUT:5e4,TOOL_BRIEF:60};Ve="flow-obs-";});var q={};L(q,{MacOsKeyVaultProvider:()=>x});var M,x,z=R(()=>{"use strict";M=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 M("security",["find-generic-password","-w","-a",n,"-s",t]);return r.trim()||null}catch{return null}}async setSecret(t,n,r){await M("security",["add-generic-password","-U","-a",n,"-s",t,"-w",r]);}async deleteSecret(t,n){try{return await M("security",["delete-generic-password","-a",n,"-s",t]),!0}catch{return !1}}getStoragePath(){return "macOS Keychain"}};});var Z={};L(Z,{LinuxKeyVaultProvider:()=>H});var Q,H,ee=R(()=>{"use strict";Q=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 Q("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",m=>{m===0?s():o(new Error(`secret-tool exited with code ${m}`));}),a.stdin.write(r),a.stdin.end();});}async deleteSecret(t,n){try{return await Q("secret-tool",["clear","service",t,"account",n]),!0}catch{return !1}}getStoragePath(){return "Linux Secret Service (libsecret)"}};});var te={};L(te,{WindowsKeyVaultProvider:()=>V});var V,ne=R(()=>{"use strict";V=class{static async isAvailable(){try{return await A("keytar").getPassword("__flow_probe__","__flow_probe__"),!0}catch{return !1}}async getSecret(t,n){return A("keytar").getPassword(t,n)}async setSecret(t,n,r){await A("keytar").setPassword(t,n,r);}async deleteSecret(t,n){return A("keytar").deletePassword(t,n)}getStoragePath(){return "Windows Credential Manager"}};});var he=Ie((Rn,ft)=>{ft.exports={name:"@ciandt-flow/flow-ai-obs",version:"0.12.0",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 $={credentials:"credentials","token-cache":"tokenCache"};function _(){let e=p__namespace.default.homedir();if(process.platform==="darwin")return f__namespace.default.join(e,"Library","Preferences",y,T);if(process.platform==="win32"){let n=process.env.APPDATA??f__namespace.default.join(e,"AppData","Roaming");return f__namespace.default.join(n,y,T)}let t=process.env.XDG_CONFIG_HOME??f__namespace.default.join(e,".config");return f__namespace.default.join(t,y,T)}function D(){try{let e=i__namespace.default.readFileSync(_(),"utf8");return JSON.parse(e)}catch{return {}}}function X(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 w=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=D(),s=$[n]??n,o=r[s];return o?typeof o=="string"?o:JSON.stringify(o):null}async setSecret(t,n,r){let s=D(),o=$[n]??n;if(n==="token-cache")try{s[o]=JSON.parse(r);}catch{s[o]=r;}else s[o]=r;X(s);}async deleteSecret(t,n){let r=D(),s=$[n]??n;return s in r?(delete r[s],X(r),true):false}getStoragePath(){return `config.json (unencrypted) \u2014 ${_()}`}};async function re(){return process.env[u.FLOW_OBS_USE_JSON_VAULT]==="1"?new w:await Qe()??new w}async function Qe(){switch(process.platform){case "darwin":{let{MacOsKeyVaultProvider:e}=await Promise.resolve().then(()=>(z(),q));return await e.isAvailable()?new e:null}case "linux":{let{LinuxKeyVaultProvider:e}=await Promise.resolve().then(()=>(ee(),Z));return await e.isAvailable()?new e:null}case "win32":{let{WindowsKeyVaultProvider:e}=await Promise.resolve().then(()=>(ne(),te));return await e.isAvailable()?new e:null}default:return null}}l();var Ze=E.SERVICE,et=E.ACCOUNT_CREDS;E.ACCOUNT_TOKEN;var Y=null;function tt(){return Y||(Y=re()),Y}async function se(){let t=await(await tt()).getSecret(Ze,et);if(!t)return null;try{return JSON.parse(t)}catch{return null}}l();l();l();f.join(p.tmpdir(),F);!process.env.NO_COLOR&&process.stdout.isTTY;function j(){return process.platform==="win32"?false:process.getuid?.()===0}function oe(){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 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(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 ie="flow-ai-obs",ae="config.json";function le(){if(process.platform==="win32"){let n=process.env.APPDATA||f__namespace.join(p__namespace.homedir(),"AppData","Roaming");return f__namespace.join(n,ie,ae)}let e=oe(),t=process.env.XDG_CONFIG_HOME||f__namespace.join(e.home,".config");return f__namespace.join(t,ie,ae)}var lt=U.LOCK_STALE_MS;function ue(e){try{let t=i__namespace.statSync(e);Date.now()-t.mtimeMs>lt&&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 pe(e){try{i__namespace.unlinkSync(e);}catch{}}function ut(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 fe(e,t){let n=P(),r=n+".lock",s=[];i__namespace.mkdirSync(f__namespace.dirname(n),{recursive:true}),ue(r);try{if(i__namespace.existsSync(n)){i__namespace.copyFileSync(n,n+".bkp");try{i__namespace.chmodSync(n+".bkp",384);}catch{}}let o=le();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 m=a.env&&typeof a.env=="object"?a.env:{};delete m.OTEL_EXPORTER_OTLP_HEADERS;let{getFlowUrls:we}=(l(),Ce(K)),Oe=we().OTEL_ENDPOINT,ve={...N,OTEL_EXPORTER_OTLP_ENDPOINT:e??Oe};a.env={...m,...ve,...t??{}},a.otelHeadersHelper="flow-ai-obs otel-headers",(!a.hooks||typeof a.hooks!="object"||Array.isArray(a.hooks))&&(a.hooks={});let Ae=(c,v)=>({matcher:"",hooks:[{type:"command",command:`flow-ai-obs ${c}`,timeout:v}]}),Re=["UserPromptSubmit","PreToolUse","PostToolUse","Stop"],J=a.hooks;for(let c of Re){let v=ut(J[c],Ae(c,b[c]));v.length>1&&s.push(c),J[c]=v;}i__namespace.writeFileSync(n,JSON.stringify(a,null,2)+`
3
- `,{encoding:"utf8",mode:384});try{i__namespace.chmodSync(n,384);}catch{}}finally{pe(r);}return {settingsPath:n,preserved:s}}function de(e){let t=P(),n=t+".lock";i__namespace.mkdirSync(f__namespace.dirname(t),{recursive:true}),ue(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{pe(n);}}l();function ge(e){if(!e)return null;try{let t=e.split(".");if(t.length<2)return null;let n=JSON.parse(Buffer.from(t[1].replace(/-/g,"+").replace(/_/g,"/"),"base64").toString("utf8")),{clientId: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 B;function ye(){return B||(B=he()),B}var Te=f__namespace.default.join(p__namespace.default.tmpdir(),"flow-obs-update-cache.json"),ht=1440*60*1e3,Et=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 Tt(){try{let e=JSON.parse(i__namespace.default.readFileSync(Te,"utf8"));return typeof e.latestVersion!="string"||Date.now()-e.checkedAt>=ht?null:e}catch{return null}}function _t(e,t,n=Date.now()){try{i__namespace.default.writeFileSync(Te,JSON.stringify({latestVersion:e,updatePriority:t??null,checkedAt:n}),{mode:384});}catch{}}function St(e){let t=ye().name,n=dt__default.default.get(`https://registry.npmjs.org/${encodeURIComponent(t)}/latest`,{timeout:Et},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 _e(){try{if(Tt())return;setImmediate(()=>{St((e,t)=>{e||!t||yt(ye().version,t.version)&&_t(t.version,t.updatePriority,0);});});}catch{}}var wt=f__namespace.default.resolve(__dirname,".."),Ot=process.env.INIT_CWD?f__namespace.default.resolve(process.env.INIT_CWD):null;Ot===wt&&process.exit(0);j()&&(process.stderr.write(`
2
+ 'use strict';var child_process=require('child_process'),util=require('util'),i=require('fs'),p=require('path'),f=require('os'),mt=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 p__namespace=/*#__PURE__*/_interopNamespace(p);var f__namespace=/*#__PURE__*/_interopNamespace(f);var mt__default=/*#__PURE__*/_interopDefault(mt);var I=Object.defineProperty;var Pe=Object.getOwnPropertyDescriptor;var Ie=Object.getOwnPropertyNames;var Ue=Object.prototype.hasOwnProperty;var O=(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 v=(e,t,r)=>()=>{if(r)throw r[0];try{return e&&(t=e(e=0)),t}catch(n){throw r=[n],n}};var Ne=(e,t)=>()=>{try{return t||e((t={exports:{}}).exports,t),t.exports}catch(r){throw t=0,r}},L=(e,t)=>{for(var r in t)I(e,r,{get:t[r],enumerable:true});},be=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of Ie(t))!Ue.call(e,s)&&s!==r&&I(e,s,{get:()=>t[s],enumerable:!(n=Pe(t,s))||n.enumerable});return e};var Ce=e=>be(I({},"__esModule",{value:true}),e);var q={};L(q,{AUTH_ENGINE:()=>N,BUFFER:()=>xe,CONFIG_DIR_NAME:()=>h,CONFIG_FILE_NAME:()=>_,DEBUG_LOG_FILENAME:()=>$,ENV:()=>u,FEATURES:()=>De,FLOW_URLS:()=>$e,HOOK_TIMEOUTS:()=>C,INSTALLER:()=>b,NATIVE_OTEL:()=>U,OTLP:()=>Me,STATE_FILE_PREFIX:()=>We,TRACE_LIMITS:()=>He,VALIDATION:()=>F,VAULT:()=>E,getFlowBaseUrl:()=>R,getFlowUrls:()=>k,getMetrics:()=>Ve});function R(){let e=process.env.FLOW_BASE_URL;return e&&e.trim()?e.trim():Fe}function k(){let e=R();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 Ve(){let e=R();return {API_URL:process.env.FLOW_METRICS_URL||`${e}/metrics-collector-api/log-event`,BOOSTER:"flow-ai-obs"}}var Fe,$e,E,h,_,Me,U,u,De,N,b,C,xe,F,$,He,We,c=v(()=>{"use strict";Fe="https://flow.ciandt.com";$e=k(),E={SERVICE:"flow-plugins-cli",ACCOUNT_CREDS:"credentials",ACCOUNT_TOKEN:"token-cache"},h="FLOW-nodejs",_="config.json",Me={SCOPE_NAME:"flow-ai-obs",SCOPE_VERSION:"0.1.0"},U={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_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",FLOW_API_KEY:"FLOW_API_KEY",OTEL_EXPORTER_OTLP_HEADERS:"OTEL_EXPORTER_OTLP_HEADERS",FLOW_BASE_URL:"FLOW_BASE_URL"},De={KEYCHAIN_ENABLED:!1},N={REQUEST_TIMEOUT_MS:1e4,MAX_RETRY_ATTEMPTS:3,RETRY_DELAY_MS:1e3},b={LOCK_STALE_MS:3e4,CONNECTIVITY_MAX_RETRY:3,CONNECTIVITY_RETRY_MS:2e3,CLI:"flow-ai-obs "},C={UserPromptSubmit:30,PreToolUse:3,PostToolUse:10,Stop:15},xe={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},F={API_KEY_MAX_LENGTH:1024,API_KEY_PATTERN:/^[\x21-\x7E]+$/,EMAIL_MAX_LENGTH:254,EMAIL_HEADER_PATTERN:/^[\x21-\x7E]+$/},$="flow-ai-obs-debug.log",He={TOOL_INPUT:2e4,TOOL_OUTPUT:2e4,TRACE_OUTPUT:2e4,USER_INSTRUCTION:1e4,TRACE_INPUT:5e4,TOOL_BRIEF:60};We="flow-obs-";});var Z={};L(Z,{MacOsKeyVaultProvider:()=>H});var x,H,Q=v(()=>{"use strict";x=util.promisify(child_process.execFile),H=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 x("security",["find-generic-password","-w","-a",r,"-s",t]);return n.trim()||null}catch{return null}}async setSecret(t,r,n){await x("security",["add-generic-password","-U","-a",r,"-s",t,"-w",n]);}async deleteSecret(t,r){try{return await x("security",["delete-generic-password","-a",r,"-s",t]),!0}catch{return !1}}getStoragePath(){return "macOS Keychain"}};});var te={};L(te,{LinuxKeyVaultProvider:()=>V});var ee,V,re=v(()=>{"use strict";ee=util.promisify(child_process.execFile),V=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 ee("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 ee("secret-tool",["clear","service",t,"account",r]),!0}catch{return !1}}getStoragePath(){return "Linux Secret Service (libsecret)"}};});var ne={};L(ne,{WindowsKeyVaultProvider:()=>W});var W,se=v(()=>{"use strict";W=class{static async isAvailable(){try{return await O("keytar").getPassword("__flow_probe__","__flow_probe__"),!0}catch{return !1}}async getSecret(t,r){return O("keytar").getPassword(t,r)}async setSecret(t,r,n){await O("keytar").setPassword(t,r,n);}async deleteSecret(t,r){return O("keytar").deletePassword(t,r)}getStoragePath(){return "Windows Credential Manager"}};});var _e=Ne(($r,dt)=>{dt.exports={name:"@ciandt-flow/flow-ai-obs",version:"0.12.1-beta.43",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"}};});c();c();var M={credentials:"credentials","token-cache":"tokenCache"};function T(){let e=f__namespace.default.homedir();if(process.platform==="darwin")return p__namespace.default.join(e,"Library","Preferences",h,_);if(process.platform==="win32"){let r=process.env.APPDATA??p__namespace.default.join(e,"AppData","Roaming");return p__namespace.default.join(r,h,_)}let t=process.env.XDG_CONFIG_HOME??p__namespace.default.join(e,".config");return p__namespace.default.join(t,h,_)}function D(){try{let e=i__namespace.default.readFileSync(T(),"utf8");return JSON.parse(e)}catch{return {}}}function z(e){let t=T();i__namespace.default.mkdirSync(p__namespace.default.dirname(t),{recursive:true}),i__namespace.default.writeFileSync(t,JSON.stringify(e,null,2),{encoding:"utf8",mode:384});}var S=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=M[r]??r,o=n[s];return o?typeof o=="string"?o:JSON.stringify(o):null}async setSecret(t,r,n){let s=D(),o=M[r]??r;if(r==="token-cache")try{s[o]=JSON.parse(n);}catch{s[o]=n;}else s[o]=n;z(s);}async deleteSecret(t,r){let n=D(),s=M[r]??r;return s in n?(delete n[s],z(n),true):false}getStoragePath(){return `config.json (unencrypted) \u2014 ${T()}`}};async function oe(){return process.env[u.FLOW_OBS_USE_JSON_VAULT]==="1"?new S:await Qe()??new S}async function Qe(){switch(process.platform){case "darwin":{let{MacOsKeyVaultProvider:e}=await Promise.resolve().then(()=>(Q(),Z));return await e.isAvailable()?new e:null}case "linux":{let{LinuxKeyVaultProvider:e}=await Promise.resolve().then(()=>(re(),te));return await e.isAvailable()?new e:null}case "win32":{let{WindowsKeyVaultProvider:e}=await Promise.resolve().then(()=>(se(),ne));return await e.isAvailable()?new e:null}default:return null}}c();var et=E.SERVICE,tt=E.ACCOUNT_CREDS;E.ACCOUNT_TOKEN;var Y=null;function rt(){return Y||(Y=oe()),Y}async function ie(){let t=await(await rt()).getSecret(et,tt);if(!t)return null;try{return JSON.parse(t)}catch{return null}}c();c();c();p.join(f.tmpdir(),$);!process.env.NO_COLOR&&process.stdout.isTTY;function G(){return process.platform==="win32"?false:process.getuid?.()===0}function ce(){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:f__namespace.homedir(),username:process.env.SUDO_USER||process.env.USER||f__namespace.userInfo().username}}function P(){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 p__namespace.join(t,".claude","settings.json")}return p__namespace.join(f__namespace.homedir(),".claude","settings.json")}if(process.platform==="win32"){let e=process.env.USERPROFILE||f__namespace.homedir();return p__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 p__namespace.join(t,".claude","settings.json")}return p__namespace.join(f__namespace.homedir(),".claude","settings.json")}var le="flow-ai-obs",ue="config.json";function pe(){if(process.platform==="win32"){let r=process.env.APPDATA||p__namespace.join(f__namespace.homedir(),"AppData","Roaming");return p__namespace.join(r,le,ue)}let e=ce(),t=process.env.XDG_CONFIG_HOME||p__namespace.join(e.home,".config");return p__namespace.join(t,le,ue)}var lt=b.LOCK_STALE_MS;function de(e){try{let t=i__namespace.statSync(e);Date.now()-t.mtimeMs>lt&&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 me(e){try{i__namespace.unlinkSync(e);}catch{}}function ut(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 ge(e,t){let r=P(),n=r+".lock",s=[];i__namespace.mkdirSync(p__namespace.dirname(r),{recursive:true}),de(n);try{if(i__namespace.existsSync(r)){i__namespace.copyFileSync(r,r+".bkp");try{i__namespace.chmodSync(r+".bkp",384);}catch{}}let o=pe();if(i__namespace.existsSync(o)){let l=o+".bkp";i__namespace.copyFileSync(o,l);try{i__namespace.chmodSync(l,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:Oe}=(c(),Ce(q)),ve=Oe().OTEL_ENDPOINT,Le={...U,OTEL_EXPORTER_OTLP_ENDPOINT:e??ve};a.env={...g,...Le,...t??{}},a.otelHeadersHelper="flow-ai-obs otel-headers",(!a.hooks||typeof a.hooks!="object"||Array.isArray(a.hooks))&&(a.hooks={});let Re=(l,A)=>({matcher:"",hooks:[{type:"command",command:`flow-ai-obs ${l}`,timeout:A}]}),ke=["UserPromptSubmit","PreToolUse","PostToolUse","Stop"],X=a.hooks;for(let l of ke){let A=ut(X[l],Re(l,C[l]));A.length>1&&s.push(l),X[l]=A;}i__namespace.writeFileSync(r,JSON.stringify(a,null,2)+`
3
+ `,{encoding:"utf8",mode:384});try{i__namespace.chmodSync(r,384);}catch{}}finally{me(n);}return {settingsPath:r,preserved:s}}function K(e){let t=P(),r=t+".lock";i__namespace.mkdirSync(p__namespace.dirname(t),{recursive:true}),de(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{me(r);}}c();c();function Ee(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 he(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}.`}c();var J;function ye(){return J||(J=_e()),J}var Se=p__namespace.default.join(f__namespace.default.tmpdir(),"flow-obs-update-cache.json"),ht=1440*60*1e3,_t=3e3;function Tt(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(Se,"utf8"));return typeof e.latestVersion!="string"||Date.now()-e.checkedAt>=ht?null:e}catch{return null}}function St(e,t,r=Date.now()){try{i__namespace.default.writeFileSync(Se,JSON.stringify({latestVersion:e,updatePriority:t??null,checkedAt:r}),{mode:384});}catch{}}function wt(e){let t=ye().name,r=mt__default.default.get(`https://registry.npmjs.org/${encodeURIComponent(t)}/latest`,{timeout:_t},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 we(){try{if(yt())return;setImmediate(()=>{wt((e,t)=>{e||!t||Tt(ye().version,t.version)&&St(t.version,t.updatePriority,0);});});}catch{}}var At=p__namespace.default.resolve(__dirname,".."),Ot=process.env.INIT_CWD?p__namespace.default.resolve(process.env.INIT_CWD):null;Ot===At&&process.exit(0);G()&&(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{fe();}catch{}let e=await se();if(!e){process.stderr.write(`
8
+ `),process.exit(1));async function vt(){try{ge();}catch{}let e=await ie();if(!e){process.stderr.write(`
9
9
  [flow-ai-obs] No credentials found.
10
- Run \`flow-ai-obs auth login\` to authenticate and enable telemetry.
10
+ Run \`flow-ai-obs login\` to authenticate and enable telemetry.
11
11
 
12
- `);return}let t=ge(process.env[u.ANTHROPIC_AUTH_TOKEN]);if(!t||t.clientId!==e.clientId||t.clientSecret!==e.clientSecret||t.tenant!==e.tenant)try{let r=me(e);de({[u.ANTHROPIC_AUTH_TOKEN]:r});}catch{}}vt().catch(()=>{}).finally(()=>_e());
12
+ `);return}let t=Ee(process.env[u.ANTHROPIC_AUTH_TOKEN]);if(!t||t.clientId!==e.clientId||t.clientSecret!==e.clientSecret||t.tenant!==e.tenant)try{let n=he(e);K({[u.ANTHROPIC_AUTH_TOKEN]:n});}catch{}}vt().catch(()=>{}).finally(()=>we());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ciandt-flow/flow-ai-obs",
3
- "version": "0.12.0",
3
+ "version": "0.12.1-beta.43",
4
4
  "description": "Claude Code hooks for Langfuse OTLP tracing — cross-platform",
5
5
  "main": "dist/index.js",
6
6
  "bin": {