@ciandt-flow/flow-ai-obs 0.7.0-beta.537 → 0.7.0-beta.552
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +153 -155
- package/dist/index.js +14 -14
- package/dist/setup.js +5 -5
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,210 +1,208 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
'use strict';var
|
|
3
|
-
`);}catch(i){throw r.close(),i}if(r.close(),e!==void 0)return e;throw new Error("Too many invalid attempts for yes/no prompt")}async function
|
|
2
|
+
'use strict';var Ne=require('readline/promises'),hs=require('https'),g=require('fs'),dt=require('os'),Rt=require('path'),child_process=require('child_process'),Cs=require('http'),util=require('util'),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 Ne__namespace=/*#__PURE__*/_interopNamespace(Ne);var hs__default=/*#__PURE__*/_interopDefault(hs);var g__namespace=/*#__PURE__*/_interopNamespace(g);var dt__namespace=/*#__PURE__*/_interopNamespace(dt);var Rt__namespace=/*#__PURE__*/_interopNamespace(Rt);var Cs__default=/*#__PURE__*/_interopDefault(Cs);var be=Object.defineProperty;var ls=Object.getOwnPropertyDescriptor;var us=Object.getOwnPropertyNames;var ds=Object.prototype.hasOwnProperty;var xt=(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 m=(t,e,r)=>()=>{if(r)throw r[0];try{return t&&(e=t(t=0)),e}catch(n){throw r=[n],n}};var ps=(t,e)=>()=>{try{return e||t((e={exports:{}}).exports,e),e.exports}catch(r){throw e=0,r}},W=(t,e)=>{for(var r in e)be(t,r,{get:e[r],enumerable:true});},fs=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of us(e))!ds.call(t,s)&&s!==r&&be(t,s,{get:()=>e[s],enumerable:!(n=ls(e,s))||n.enumerable});return t};var P=t=>fs(be({},"__esModule",{value:true}),t);var ae=ps((li,ms)=>{ms.exports={name:"@ciandt-flow/flow-ai-obs",version:"0.7.0-beta.552",description:"Claude Code hooks for Langfuse OTLP tracing \u2014 cross-platform",main:"dist/index.js",bin:{"flow-ai-obs":"dist/cli.js","flow-ai-obs-setup":"dist/setup.js"},scripts:{build:"tsup",test:"jest",typecheck:"tsc --noEmit",lint:"eslint src bin scripts",format:'prettier --write "src/**/*.ts" "bin/**/*.ts" "scripts/**/*.ts"',"format:check":'prettier --check "src/**/*.ts" "bin/**/*.ts" "scripts/**/*.ts"',"security-scan":"trufflehog filesystem src/ --fail --no-update --exclude-paths .trufflehogignore",postinstall:`node -e "require('fs').existsSync('dist/setup.js') && require('child_process').execFileSync(process.execPath, ['dist/setup.js'], {stdio:'inherit'})"`,prepublishOnly:"npm run security-scan && npm run build","release:npm":"changeset publish",changeset:"changeset","version-packages":"changeset version","install:hooks":"node dist/cli.js install","auth:login":"node dist/cli.js auth login","auth:logout":"node dist/cli.js auth logout","auth:status":"node dist/cli.js auth status",smoke:"bash scripts/smoke-test.sh","smoke:debug":"bash scripts/smoke-test.sh --debug","smoke:send":"bash scripts/smoke-test.sh --send --allow-http --debug"},files:["dist/","README.md","LICENSE.md"],keywords:["claude-code","langfuse","observability","otlp","hooks","flow","ciandt"],author:"CI&T Flow Team",license:"SEE LICENSE IN LICENSE.md",private:!1,dependencies:{},optionalDependencies:{keytar:"7.9.0"},devDependencies:{"@changesets/changelog-github":"^0.6.0","@changesets/cli":"^2.30.0","@types/jest":"^30.0.0","@types/node":"^25.8.0",jest:"^30.4.2","ts-jest":"^29.4.9",tsup:"^8.5.1","eslint-config-prettier":"^10.1.5",prettier:"^3.5.3",typescript:"^6.0.3","typescript-eslint":"^8.33.0"},engines:{node:">=18.0.0"},overrides:{esbuild:"^0.28.1"},publishConfig:{registry:"https://registry.npmjs.org",access:"public"},repository:{type:"git",url:"git+https://github.com/CI-T-HyperX/flow-codeassistant-observability.git"}};});var Ce={};W(Ce,{bold:()=>b,cyan:()=>I,dim:()=>w,green:()=>L,red:()=>R,yellow:()=>_});function _t(t,e){return gs?r=>`\x1B[${t}m${r}\x1B[${e}m`:r=>r}var gs,L,R,_,I,b,w,it=m(()=>{"use strict";gs=!process.env.NO_COLOR&&process.stdout.isTTY;L=_t("32","39"),R=_t("31","39"),_=_t("33","39"),I=_t("36","39"),b=_t("1","22"),w=_t("2","22");});function at(){return process.stdout.isTTY===true&&process.stdin.isTTY===true&&!process.argv.includes("--no-interactive")}async function ce(t,e){let r=Ne__namespace.createInterface({input:process.stdin,output:process.stdout}),s=`${t} ${e===true?"(Y/n)":e===false?"(y/N)":"(y/n)"}: `;for(let o=1;o<=3;o++)try{let i=(await r.question(s)).trim().toLowerCase();if(i===""&&e!==void 0)return r.close(),e;if(i==="y"||i==="yes")return r.close(),!0;if(i==="n"||i==="no")return r.close(),!1;o<3&&process.stdout.write(` Invalid input. Please answer "y" or "n".
|
|
3
|
+
`);}catch(i){throw r.close(),i}if(r.close(),e!==void 0)return e;throw new Error("Too many invalid attempts for yes/no prompt")}async function le(t,e){let r=Ne__namespace.createInterface({input:process.stdin,output:process.stdout});try{let n=(await r.question(`${t}: `)).trim();if(e){let s=e(n);if(s)throw new Error(s)}return n}catch(n){throw n}finally{r.close();}}var Ue=m(()=>{"use strict";});var kt={};W(kt,{checkForUpdate:()=>Os,checkForUpdateInteractive:()=>ks,fetchLatestVersionAsync:()=>Ar,isNewer:()=>Ot,primeUpdateCache:()=>vs});function C(){return $e||($e=ae()),$e}function Ot(t,e){let r=o=>{let i=String(o).replace(/^v/,"").match(/^(\d+)\.(\d+)\.(\d+)/);return i?[+i[1],+i[2],+i[3]]:null},n=r(t),s=r(e);return !n||!s?false:s[0]!==n[0]?s[0]>n[0]:s[1]!==n[1]?s[1]>n[1]:s[2]>n[2]}function De(){try{let t=JSON.parse(g__namespace.default.readFileSync(vr,"utf8"));return typeof t.latestVersion!="string"||Date.now()-t.checkedAt>=Ss?null:t}catch{return null}}function Me(t,e,r=Date.now()){try{g__namespace.default.writeFileSync(vr,JSON.stringify({latestVersion:t,updatePriority:e??null,checkedAt:r}),{mode:384});}catch{}}function Be(t){let e=C().name,r=hs__default.default.get(`https://registry.npmjs.org/${encodeURIComponent(e)}/latest`,{timeout:Ts},n=>{if(n.statusCode!==200)return n.resume(),t(new Error(`HTTP ${n.statusCode}`));let s="";n.setEncoding("utf8"),n.on("data",o=>{s+=o;}),n.on("end",()=>{try{let o=JSON.parse(s);if(typeof o.version!="string")throw new Error("no version field");t(null,{version:o.version,updatePriority:typeof o.updatePriority=="string"?o.updatePriority:null});}catch(o){t(o);}});});r.on("error",t),r.on("timeout",()=>{r.destroy(new Error("timeout"));});}function Fe(t){let e=C().name,n=` Update available: ${C().version} \u2192 ${t}`,s=` Run: npm install -g ${e}`,o=Math.max(n.length,s.length)+2,i="\u2500".repeat(o);process.stderr.write(`
|
|
4
4
|
\u256D${i}\u256E
|
|
5
5
|
\u2502${n.padEnd(o)}\u2502
|
|
6
6
|
\u2502${s.padEnd(o)}\u2502
|
|
7
7
|
\u2570${i}\u256F
|
|
8
8
|
|
|
9
|
-
`);}function
|
|
9
|
+
`);}function xe(t){let e=C().name;process.stderr.write(`
|
|
10
10
|
[${e}] Critical update detected \u2014 auto-updating to ${t}...
|
|
11
11
|
|
|
12
|
-
`),child_process.spawn("npm",["install","-g",`${e}@${t}`],{detached:true,stdio:"ignore",windowsHide:true}).unref();}async function
|
|
13
|
-
\u256D${
|
|
12
|
+
`),child_process.spawn("npm",["install","-g",`${e}@${t}`],{detached:true,stdio:"ignore",windowsHide:true}).unref();}async function ys(t,e=1e4){let r=xt("readline"),n=C().name,o=` Update available: ${C().version} \u2192 ${t}`,i=` Run: npm install -g ${n}`,a=" Install now? [y/N]: ",c=Math.max(o.length,i.length,a.length-2)+2,u="\u2500".repeat(c);return process.stderr.write(`
|
|
13
|
+
\u256D${u}\u256E
|
|
14
14
|
\u2502${o.padEnd(c)}\u2502
|
|
15
15
|
\u2502${i.padEnd(c)}\u2502
|
|
16
16
|
\u2502${a.padEnd(c)}\u2502
|
|
17
|
-
\u2570${
|
|
18
|
-
`),new Promise(
|
|
19
|
-
`),
|
|
17
|
+
\u2570${u}\u256F
|
|
18
|
+
`),new Promise(d=>{let h=r.createInterface({input:process.stdin,output:void 0,terminal:false}),E=false;function S(O){E||(E=true,clearTimeout(v),h.close(),process.stderr.write(`
|
|
19
|
+
`),d(O));}let v=setTimeout(()=>S(false),e);h.once("line",O=>S(O.trim().toLowerCase()==="y")),h.once("close",()=>S(false));})}async function _s(t){let e=C().name;return process.stderr.write(` Installing ${e}@${t}...
|
|
20
20
|
`),new Promise(r=>{let n=child_process.spawn("npm",["install","-g",`${e}@${t}`],{stdio:"inherit"});n.on("close",s=>{s!==0?process.stderr.write(` \u2717 Update failed \u2014 continuing with current version.
|
|
21
21
|
|
|
22
22
|
`):process.stderr.write(` \u2713 Updated to ${t}. Please restart the command.
|
|
23
23
|
|
|
24
24
|
`),r();}),n.on("error",()=>{process.stderr.write(` \u2717 Update failed \u2014 continuing with current version.
|
|
25
25
|
|
|
26
|
-
`),r();});})}function
|
|
27
|
-
|
|
26
|
+
`),r();});})}function Ar(){return new Promise(t=>{Be((e,r)=>t(e||!r?null:r));})}function Os(){try{let t=De();if(t){Ot(C().version,t.latestVersion)&&(t.updatePriority==="auto"?xe(t.latestVersion):Fe(t.latestVersion));return}setImmediate(()=>{Be((e,r)=>{e||!r||(Me(r.version,r.updatePriority),Ot(C().version,r.version)&&(r.updatePriority==="auto"?xe(r.version):Fe(r.version)));});});}catch{}}async function ks(t={}){try{let e=De();if(e){if(!Ot(C().version,e.latestVersion))return}else {let n=await Ar();if(!n||(Me(n.version,n.updatePriority),!Ot(C().version,n.version)))return;e={latestVersion:n.version,updatePriority:n.updatePriority,checkedAt:Date.now()};}if(e.updatePriority==="auto"){xe(e.latestVersion);return}if(!at()){Fe(e.latestVersion);return}await ys(e.latestVersion,t.timeoutMs)&&await _s(e.latestVersion);}catch{}}function vs(){try{if(De())return;setImmediate(()=>{Be((t,e)=>{t||!e||Ot(C().version,e.version)&&Me(e.version,e.updatePriority,0);});});}catch{}}var $e,vr,Ss,Ts,vt=m(()=>{"use strict";Ue();vr=Rt__namespace.default.join(dt__namespace.default.tmpdir(),"flow-obs-update-cache.json"),Ss=1440*60*1e3,Ts=3e3;});function ct(){let t=process.env.FLOW_BASE_URL;return t&&t.trim()?t.trim():Dt}function At(){let t=ct();return {AUTH_ENGINE:process.env.FLOW_AUTH_ENGINE_URL||`${t}/auth-engine-api/v2/api-key/token`,GATEWAY_TRACES:`${He}/flow-langfuse-gateway/v1/traces`,GATEWAY_HEALTH:`${He}/flow-langfuse-gateway/v1/health`,OTEL_ENDPOINT:process.env.FLOW_OTEL_ENDPOINT_URL||`${He}`}}function Mt(){let t=ct();return {ANTHROPIC_BASE_URL:process.env.FLOW_LLM_PROXY_URL??`${t}/flow-llm-proxy/`,ANTHROPIC_MODEL:process.env.FLOW_LLM_PROXY_MODEL??"anthropic.claude-4-6-sonnet",ANTHROPIC_SMALL_FAST_MODEL:process.env.FLOW_LLM_PROXY_SMALL_MODEL??"anthropic.claude-4-6-sonnet",CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS:"1"}}function Ve(){let t=ct();return {API_URL:process.env.FLOW_METRICS_URL||`${t}/metrics-collector-api/log-event`,BOOSTER:"flow-ai-obs"}}var He,Dt,As,ue,de,pe,je,V,p,Lr,We,D,Rr,Y,k=m(()=>{"use strict";He="https://dev.flow.ciandt.com/otel",Dt="https://dev.flow.ciandt.com";As=At(),ue={SERVICE:"flow-plugins-cli",ACCOUNT_CREDS:"credentials",ACCOUNT_TOKEN:"token-cache"},de="FLOW-nodejs",pe="config.json",je={SCOPE_NAME:"flow-ai-obs",SCOPE_VERSION:"0.1.0"};V={CLAUDE_CODE_ENABLE_TELEMETRY:"1",OTEL_EXPORTER_OTLP_ENDPOINT:As.OTEL_ENDPOINT,OTEL_EXPORTER_OTLP_PROTOCOL:"http/json",OTEL_METRICS_EXPORTER:"otlp",OTEL_LOGS_EXPORTER:"otlp",OTEL_LOG_TOOL_DETAILS:"1",OTEL_LOG_USER_PROMPTS:"1"},p={FLOW_TELEMETRY:"FLOW_TELEMETRY",FLOW_TELEMETRY_GATEWAY:"FLOW_TELEMETRY_GATEWAY_URL",LANGFUSE_BASE_URL:"LANGFUSE_BASE_URL",LANGFUSE_PUBLIC_KEY:"LANGFUSE_PUBLIC_KEY",LANGFUSE_SECRET_KEY:"LANGFUSE_SECRET_KEY",ANTHROPIC_MODEL:"ANTHROPIC_MODEL",ANTHROPIC_AUTH_TOKEN:"ANTHROPIC_AUTH_TOKEN",FLOW_OBS_DEBUG:"FLOW_TELEMETRY_DEBUG",FLOW_OBS_ALLOW_HTTP:"FLOW_TELEMETRY_ALLOW_HTTP",BUFFER_TTL_DAYS:"FLOW_TELEMETRY_BUFFER_TTL_DAYS",BUFFER_MAX_FILES:"FLOW_TELEMETRY_BUFFER_MAX_FILES",FLOW_USER_EMAIL:"FLOW_USER_EMAIL"},Lr={LOCK_STALE_MS:3e4,CONNECTIVITY_MAX_RETRY:3,CONNECTIVITY_RETRY_MS:2e3},We={UserPromptSubmit:5,PreToolUse:3,PostToolUse:10,Stop:15},D={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},Rr="flow-ai-obs-debug.log",Y={TOOL_INPUT:2e4,TOOL_OUTPUT:2e4,TRACE_OUTPUT:2e4,USER_INSTRUCTION:1e4,TRACE_INPUT:5e4,TOOL_BRIEF:60};});function l(...t){if(process.env[p.FLOW_OBS_DEBUG]!=="1")return;let e=`[${new Date().toISOString()}] ${t.join(" ")}
|
|
27
|
+
`;try{g.writeFileSync(Ps,e,{flag:"a"});}catch(r){process.stderr.write(`[flow-obs debug ERROR] ${r.message}
|
|
28
|
+
`);}}var Ps,M=m(()=>{"use strict";k();Ps=Rt.join(dt.tmpdir(),Rr);});function Us(t){if(!Ns.test(t))throw new Error(`Invalid tenant value: "${t}". Tenant must be lowercase alphanumeric and hyphens (1-64 chars).`)}function $s(t,e){let r=e.length>400?e.slice(0,400)+"\u2026":e;l("toAuthError",`status=${t} body=${r}`);try{let n=JSON.parse(e);if(typeof n.error=="string"&&(l("toAuthError",`api_error_code=${n.error}`+(n.message?` api_message=${n.message}`:"")),Ir[n.error]))return new lt(Ir[n.error])}catch{}return t===401||t===403||t===500?new lt("Invalid credentials"):t>=400&&t<500?new lt("Authentication request was rejected"):new Error("Authentication service unavailable, please try again later")}function q(t){return new Promise((e,r)=>{try{Us(t.tenant);}catch(u){return r(u)}let n=JSON.stringify({clientSecret:t.clientSecret}),s=new URL(At().AUTH_ENGINE),o=s.protocol==="https:",i={hostname:s.hostname,port:s.port||(o?443:80),path:s.pathname+s.search,method:"POST",headers:{"Content-Type":"application/json","Content-Length":Buffer.byteLength(n),FlowTenant:t.tenant}};l("getToken",`requesting token tenant=${t.tenant} host=${i.hostname} path=${i.path}`);let c=(o?hs__default.default:Cs__default.default).request(i,u=>{let d=[];u.on("data",h=>d.push(h)),u.on("end",()=>{let h=d.join("");if((u.statusCode??0)>=400)return r($s(u.statusCode??0,h));let E;try{E=JSON.parse(h);}catch{return r(new Error("Invalid response from auth engine"))}let S=E.expires_at??new Date(Date.now()+(E.expires_in??3600)*1e3).toISOString();e({accessToken:E.access_token??"",expiresAt:S});});});c.on("error",u=>r(new Error(`Network error: ${u.message}`))),c.write(n),c.end();})}var lt,Ns,Ir,Bt=m(()=>{"use strict";k();M();lt=class extends Error{constructor(e){super(e),this.name="AuthError";}},Ns=/^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$|^[a-z0-9]$/;Ir={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 Pr(){return process.platform==="win32"?false:process.getuid?.()===0}function ut(){if(Pr())return process.stderr.write(`
|
|
29
|
+
`+R(` \u2717 flow-ai-obs is not supported in a sudo context.
|
|
28
30
|
|
|
29
31
|
`)+I(` npm install -g @ciandt-flow/flow-ai-obs
|
|
30
32
|
`)+`
|
|
31
|
-
`),1}var jt=m(()=>{"use strict";ot();});function Rr(){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 {home:e,username:process.env.SUDO_USER}}return {home:ct__namespace.homedir(),username:process.env.SUDO_USER||process.env.USER||ct__namespace.userInfo().username}}function N(){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 Rt__namespace.join(e,".claude","settings.json")}return Rt__namespace.join(ct__namespace.homedir(),".claude","settings.json")}if(process.platform==="win32"){let t=process.env.USERPROFILE||ct__namespace.homedir();return Rt__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 Rt__namespace.join(e,".claude","settings.json")}return Rt__namespace.join(ct__namespace.homedir(),".claude","settings.json")}var de=m(()=>{"use strict";jt();});function Nr(){if(process.platform==="win32"){let r=process.env.APPDATA||Rt__namespace.join(ct__namespace.homedir(),"AppData","Roaming");return Rt__namespace.join(r,br,Cr)}let t=Rr(),e=process.env.XDG_CONFIG_HOME||Rt__namespace.join(t.home,".config");return Rt__namespace.join(e,br,Cr)}function Ur(){try{let t=h__namespace.readFileSync(Nr(),"utf8");return JSON.parse(t)}catch{return {}}}function z(){let{baseUrl:t}=Ur();return typeof t!="string"||t.trim()===""?null:t.trim().replace(/\/$/,"")}function $r(t){let e=Nr();h__namespace.mkdirSync(Rt__namespace.dirname(e),{recursive:true});let n={...Ur(),baseUrl:t};h__namespace.writeFileSync(e,JSON.stringify(n,null,2)+`
|
|
32
|
-
`,{encoding:"utf8",mode:384});
|
|
33
|
-
|
|
34
|
-
`);}}var Us,H=m(()=>{"use strict";A();Us=Rt.join(ct.tmpdir(),xr);});function Ds(t){if(!xs.test(t))throw new Error(`Invalid tenant value: "${t}". Tenant must be lowercase alphanumeric and hyphens (1-64 chars).`)}function Ms(t,e){let r=e.length>400?e.slice(0,400)+"\u2026":e;u("toAuthError",`status=${t} body=${r}`);try{let n=JSON.parse(e);if(typeof n.error=="string"&&(u("toAuthError",`api_error_code=${n.error}`+(n.message?` api_message=${n.message}`:"")),Dr[n.error]))return new dt(Dr[n.error])}catch{}return t===401||t===403||t===500?new dt("Invalid credentials"):t>=400&&t<500?new dt("Authentication request was rejected"):new Error("Authentication service unavailable, please try again later")}function G(t){return new Promise((e,r)=>{try{Ds(t.tenant);}catch(l){return r(l)}let n=JSON.stringify({clientSecret:t.clientSecret}),s=new URL(Lt().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}};u("getToken",`requesting token tenant=${t.tenant} host=${i.hostname} path=${i.path}`);let c=(o?Ts__default.default:Fs__default.default).request(i,l=>{let p=[];l.on("data",y=>p.push(y)),l.on("end",()=>{let y=p.join("");if((l.statusCode??0)>=400)return r(Ms(l.statusCode??0,y));let w;try{w=JSON.parse(y);}catch{return r(new Error("Invalid response from auth engine"))}let T=w.expires_at??new Date(Date.now()+(w.expires_in??3600)*1e3).toISOString();e({accessToken:w.access_token??"",expiresAt:T});});});c.on("error",l=>r(new Error(`Network error: ${l.message}`))),c.write(n),c.end();})}var dt,xs,Dr,It=m(()=>{"use strict";A();H();dt=class extends Error{constructor(e){super(e),this.name="AuthError";}},xs=/^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$|^[a-z0-9]$/;Dr={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 Yt(){let t=ct__namespace.default.homedir();if(process.platform==="darwin")return Rt__namespace.default.join(t,"Library","Preferences",me,ge);if(process.platform==="win32"){let r=process.env.APPDATA??Rt__namespace.default.join(t,"AppData","Roaming");return Rt__namespace.default.join(r,me,ge)}let e=process.env.XDG_CONFIG_HOME??Rt__namespace.default.join(t,".config");return Rt__namespace.default.join(e,me,ge)}function Je(){try{let t=h__namespace.default.readFileSync(Yt(),"utf8");return JSON.parse(t)}catch{return {}}}function Mr(t){let e=Yt();h__namespace.default.mkdirSync(Rt__namespace.default.dirname(e),{recursive:true}),h__namespace.default.writeFileSync(e,JSON.stringify(t,null,2),{encoding:"utf8",mode:384});}var Ke,we,Br=m(()=>{"use strict";A();Ke={credentials:"credentials","token-cache":"tokenCache"};we=class{static isAvailable(){return !0}static hasExistingData(){try{if(!h__namespace.default.existsSync(Yt()))return !1;let e=JSON.parse(h__namespace.default.readFileSync(Yt(),"utf8"));return !!(e&&e.credentials)}catch{return !1}}async getSecret(e,r){let n=Je(),s=Ke[r]??r,o=n[s];return o?typeof o=="string"?o:JSON.stringify(o):null}async setSecret(e,r,n){let s=Je(),o=Ke[r]??r;if(r==="token-cache")try{s[o]=JSON.parse(n);}catch{s[o]=n;}else s[o]=n;Mr(s);}async deleteSecret(e,r){let n=Je(),s=Ke[r]??r;return s in n?(delete n[s],Mr(n),!0):!1}getStoragePath(){return `config.json (unencrypted) \u2014 ${Yt()}`}};});var Hr={};V(Hr,{MacOsKeyVaultProvider:()=>ze});var qe,ze,jr=m(()=>{"use strict";qe=util.promisify(child_process.execFile),ze=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 qe("security",["find-generic-password","-w","-a",r,"-s",e]);return n.trim()||null}catch{return null}}async setSecret(e,r,n){await qe("security",["add-generic-password","-U","-a",r,"-s",e,"-w",n]);}async deleteSecret(e,r){try{return await qe("security",["delete-generic-password","-a",r,"-s",e]),!0}catch{return !1}}getStoragePath(){return "macOS Keychain"}};});var Yr={};V(Yr,{LinuxKeyVaultProvider:()=>Xe});var Vr,Xe,Wr=m(()=>{"use strict";Vr=util.promisify(child_process.execFile),Xe=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 Vr("secret-tool",["lookup","service",e,"account",r]);return n.trim()||null}catch{return null}}async setSecret(e,r,n){await new Promise((s,o)=>{let i=child_process.spawn("secret-tool",["store","--label",e,"service",e,"account",r]);i.on("error",o),i.on("close",a=>{a===0?s():o(new Error(`secret-tool exited with code ${a}`));}),i.stdin.write(n),i.stdin.end();});}async deleteSecret(e,r){try{return await Vr("secret-tool",["clear","service",e,"account",r]),!0}catch{return !1}}getStoragePath(){return "Linux Secret Service (libsecret)"}};});var Gr={};V(Gr,{WindowsKeyVaultProvider:()=>Ze});var Ze,Kr=m(()=>{"use strict";Ze=class{static async isAvailable(){try{return await Ht("keytar").getPassword("__flow_probe__","__flow_probe__"),!0}catch{return !1}}async getSecret(e,r){return Ht("keytar").getPassword(e,r)}async setSecret(e,r,n){await Ht("keytar").setPassword(e,r,n);}async deleteSecret(e,r){return Ht("keytar").deletePassword(e,r)}getStoragePath(){return "Windows Credential Manager"}};});async function Jr(){return await zs()??new we}async function zs(){switch(process.platform){case "darwin":{let{MacOsKeyVaultProvider:t}=await Promise.resolve().then(()=>(jr(),Hr));return await t.isAvailable()?new t:null}case "linux":{let{LinuxKeyVaultProvider:t}=await Promise.resolve().then(()=>(Wr(),Yr));return await t.isAvailable()?new t:null}case "win32":{let{WindowsKeyVaultProvider:t}=await Promise.resolve().then(()=>(Kr(),Gr));return await t.isAvailable()?new t:null}default:return null}}var qr=m(()=>{"use strict";Br();});function Ct(){return Qe||(Qe=Jr()),Qe}async function R(){let e=await(await Ct()).getSecret(bt,tr);if(!e)return null;try{return JSON.parse(e)}catch{return null}}async function rr(t){if(!t.clientId||!t.clientSecret||!t.tenant)throw new Error("clientId, clientSecret and tenant are required");await(await Ct()).setSecret(bt,tr,JSON.stringify(t));}async function zr(){let t=await Ct();await t.deleteSecret(bt,tr),await t.deleteSecret(bt,er);}async function Gt(t){await(await Ct()).setSecret(bt,er,JSON.stringify({accessToken:t.accessToken,expiresAt:t.expiresAt,lastAuthCheckAt:t.lastAuthCheckAt}));}async function Pt(){let e=await(await Ct()).getSecret(bt,er);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 Ee(){let t=await Pt();return t?new Date(t.expiresAt)>new Date:false}async function pt(){let t=await Pt();if(!t||!t.accessToken)return null;try{let e=t.accessToken.split(".");if(e.length<2)return null;let r=JSON.parse(Buffer.from(e[1].replace(/-/g,"+").replace(/_/g,"/"),"base64").toString("utf8"));return r.email??r.preferred_username??r.upn??r.sub??null}catch{return null}}async function nr(){let t=await Ct();if(typeof t.getStoragePath=="function")return t.getStoragePath();let e=process.platform;return e==="darwin"?"macOS Keychain":e==="win32"?"Windows Credential Manager":"Linux Secret Service (libsecret)"}async function Xr(){let t=await R();return !!(t&&t.clientId&&t.clientSecret&&t.tenant)}var bt,tr,er,Qe,Kt=m(()=>{"use strict";qr();A();bt=fe.SERVICE,tr=fe.ACCOUNT_CREDS,er=fe.ACCOUNT_TOKEN,Qe=null;});function Qs(t){return Zs.some(e=>e.test(t))}function to(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 U(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 Zr(t){let e=Buffer.from(JSON.stringify({alg:"none",typ:"JWT"})).toString("base64url"),r=Buffer.from(JSON.stringify({clientId:t.clientId,clientSecret:t.clientSecret,tenant:t.tenant})).toString("base64url");return `${e}.${r}.`}function Nt(t){let e;try{e=new URL(t);}catch{throw new Error(`Invalid URL: ${t}`)}let r=process.env[f.FLOW_OBS_ALLOW_HTTP]==="true";if(!r&&e.protocol!=="https:")throw new Error(`URL must use HTTPS: ${t}`);if(e.username||e.password)throw new Error(`URL must not contain embedded credentials: ${t}`);if(!r&&Qs(e.hostname))throw new Error(`SSRF: private/loopback host not allowed: ${e.hostname}`);return t}async function Qr(){let t=U(process.env[f.ANTHROPIC_AUTH_TOKEN]);if(t)return {user:await pt().catch(()=>null)??t.clientId,tenant:t.tenant};if(he.KEYCHAIN_ENABLED)try{let e=await R();if(!e)return {user:"",tenant:""};let r=await pt()??e.clientId??"",n=e.tenant??"";return {user:r,tenant:n}}catch{return {user:"",tenant:""}}return {user:"",tenant:""}}function eo(){return new Date().toISOString().slice(0,10)}async function ro(t){let e=eo(),r=await Pt();if(r?.lastAuthCheckAt!==e){u("getOrRefreshToken",`daily auth check (last: ${r?.lastAuthCheckAt??"never"})`);try{let o=await G(t);try{await Gt({...o,lastAuthCheckAt:e});}catch{}return u("getOrRefreshToken",`daily check passed, expires=${o.expiresAt}`),o.accessToken}catch(o){if(o instanceof dt)throw o;u("getOrRefreshToken",`daily check network error \u2014 using cache: ${o.message}`);}}let n=r!=null&&new Date(r.expiresAt)>new Date;if(u("getOrRefreshToken",`cacheValid=${n}`),n)return u("getOrRefreshToken",`using cached token, expires=${r.expiresAt}`),r.accessToken;u("getOrRefreshToken",`token expired \u2014 refreshing via auth-engine (tenant=${t.tenant} clientId=${t.clientId})`);let s=await G(t);try{await Gt({...s,lastAuthCheckAt:e});}catch(o){u("getOrRefreshToken",`token cache save failed (non-fatal): ${o.message}`);}return u("getOrRefreshToken",`token refreshed, expires=${s.expiresAt}`),s.accessToken}function no(t,e){let r=e&&e.accessToken?e.accessToken:"";return {endpoint:t.replace(/\/$/,"")+"/flow-langfuse-gateway/v1/traces",authHeader:`Bearer ${r}`}}function so(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 q(){let t=[],e=process.env[f.ANTHROPIC_MODEL]??"",r=U(process.env[f.ANTHROPIC_AUTH_TOKEN]);u("resolveCredentials",r?"credentials resolved from ANTHROPIC_AUTH_TOKEN":"ANTHROPIC_AUTH_TOKEN absent or invalid"),r&&u("resolveCredentials",`clientId=${r.clientId}`,`tenant=${r.tenant}`),!r&&he.KEYCHAIN_ENABLED&&(r=await R(),r&&u("resolveCredentials","credentials resolved from keychain (FEATURES.KEYCHAIN_ENABLED=true)"));let n=r?r.tenant:"",s=process.env[f.FLOW_TELEMETRY]==="true",o=process.env[f.LANGFUSE_BASE_URL],i=process.env[f.LANGFUSE_PUBLIC_KEY],a=process.env[f.LANGFUSE_SECRET_KEY];if(s&&o&&i&&a){let w="",T=n;if(r)w=await pt().catch(()=>null)??r.clientId;else if(he.KEYCHAIN_ENABLED)try{let _=await R();_&&(w=await pt()??_.clientId,T=_.tenant);}catch{}let v={user:w??"",tenant:T??"",team:"",project:"",model:e};t.push({mode:"direct",...so(Nt(o),i,a),...v}),u("resolveCredentials","direct mode active",`user=${v.user}`,`tenant=${v.tenant}`);}if(!r){if(t.length===0){let w=[];return w.authError=false,w}return t}let c;try{c=await ro(r);}catch(w){if(u("resolveCredentials",`token refresh failed: ${w.message}`,`(tenant=${r.tenant} clientId=${r.clientId})`),t.length>0)return t.authError=true,t;let T=[];return T.authError=true,T}let p={user:to(c)??r.clientId,tenant:n,team:"",project:"",model:e},y=process.env[f.FLOW_TELEMETRY_GATEWAY]??ut();return t.push({mode:"gateway",...no(Nt(y),{accessToken:c}),...p}),t}async function tn(){return (await q()).length>0}function ft(){let t=process.env[f.FLOW_USER_EMAIL];if(t)return u("resolveUserEmail",`using FLOW_USER_EMAIL override: ${t}`),t;try{let e=ct__namespace.default.userInfo().username||process.env.USERNAME||process.env.USER||"",r=e.lastIndexOf("\\");if(r!==-1&&(e=e.slice(r+1)),e=e.trim().replace(/[^a-zA-Z0-9._%+\-]/g,""),!e)return u("resolveUserEmail","username empty after sanitisation \u2014 omitting x-flow-user"),console.warn("[flow-ai-obs] Could not derive x-flow-user: username is empty. Set FLOW_USER_EMAIL to fix this."),null;let n=`${e}@ciandt.com`;return u("resolveUserEmail",`derived email: ${n}`),n}catch(e){return u("resolveUserEmail",`os.userInfo() threw: ${e.message} \u2014 omitting x-flow-user`),console.warn("[flow-ai-obs] Could not derive x-flow-user from OS username. Set FLOW_USER_EMAIL to fix this."),null}}var Zs,$=m(()=>{"use strict";Kt();It();A();H();Zs=[/^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 sr(t){try{let e=h__namespace.statSync(t);Date.now()-e.mtimeMs>oo&&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 or(t){try{h__namespace.unlinkSync(t);}catch{}}function en(t,e){let n=(Array.isArray(t)?t:[]).map(s=>{if(!Array.isArray(s?.hooks))return null;let o=s.hooks.filter(i=>!i.command?.startsWith?.("flow-ai-obs "));return o.length>0?{...s,hooks:o}:null}).filter(s=>s!=null);return [e,...n]}function rn(){let t=N(),e=t+".lock",r=[];h__namespace.mkdirSync(Rt__namespace.dirname(t),{recursive:true}),sr(e);try{if(h__namespace.existsSync(t)){h__namespace.copyFileSync(t,t+".bkp");try{h__namespace.chmodSync(t+".bkp",384);}catch{}}let n={};try{n=JSON.parse(h__namespace.readFileSync(t,"utf8"));}catch{}let s=n.env&&typeof n.env=="object"?n.env:{};delete s.OTEL_EXPORTER_OTLP_HEADERS,n.env={...s,...Y,...Vt()},n.otelHeadersHelper="flow-ai-obs otel-headers",(!n.hooks||typeof n.hooks!="object"||Array.isArray(n.hooks))&&(n.hooks={});let o=(c,l)=>({matcher:"",hooks:[{type:"command",command:`flow-ai-obs ${c}`,timeout:l}]}),i=["UserPromptSubmit","PreToolUse","PostToolUse","Stop"],a=n.hooks;for(let c of i){let l=en(a[c],o(c,We[c]));l.length>1&&r.push(c),a[c]=l;}h__namespace.writeFileSync(t,JSON.stringify(n,null,2)+`
|
|
35
|
-
`,{encoding:"utf8",mode:384});try{
|
|
36
|
-
`,{encoding:"utf8",mode:384});try{h__namespace.chmodSync(e,384);}catch{}}finally{or(r);}}function nn(){let t=N(),e=t+".lock",r=[];h__namespace.mkdirSync(Rt__namespace.dirname(t),{recursive:true}),sr(e);try{if(h__namespace.existsSync(t)){h__namespace.copyFileSync(t,t+".bkp");try{h__namespace.chmodSync(t+".bkp",384);}catch{}}let n={};try{n=JSON.parse(h__namespace.readFileSync(t,"utf8"));}catch{}n.otelHeadersHelper="flow-ai-obs otel-headers",(!n.hooks||typeof n.hooks!="object"||Array.isArray(n.hooks))&&(n.hooks={});let s=(a,c)=>({matcher:"",hooks:[{type:"command",command:`flow-ai-obs ${a}`,timeout:c}]}),o=["UserPromptSubmit","PreToolUse","PostToolUse","Stop"],i=n.hooks;for(let a of o){let c=en(i[a],s(a,We[a]));c.length>1&&r.push(a),i[a]=c;}h__namespace.writeFileSync(t,JSON.stringify(n,null,2)+`
|
|
37
|
-
`,{encoding:"utf8",mode:384});try{h__namespace.chmodSync(t,384);}catch{}}finally{or(e);}return {settingsPath:t,preserved:r}}var oo,Jt=m(()=>{"use strict";A();It();de();$();oo=Fr.LOCK_STALE_MS;});function Te(){if(process.env.WSL_DISTRO_NAME&&process.platform==="linux")return child_process.spawnSync("cmd.exe",["/c","where","claude"],{encoding:"utf8",timeout:5e3}).status===0;let t=process.platform==="win32"?"where":"which";return child_process.spawnSync(t,["claude"],{encoding:"utf8",timeout:5e3}).status===0}function ar(){try{if(process.env.WSL_DISTRO_NAME&&process.platform==="linux"){let e=child_process.spawnSync("cmd.exe",["/c","claude","--version"],{encoding:"utf8",timeout:5e3});return e.status===0?e.stdout.trim():null}let t=child_process.spawnSync("claude",["--version"],{encoding:"utf8",timeout:5e3});return t.status===0?t.stdout.trim():null}catch{return null}}function sn(){if(child_process.spawnSync("node",["--version"],{encoding:"utf8",timeout:5e3}).status!==0)return {success:false,error:"no_nodejs",message:`Node.js is not installed. Install Node.js 18+ and try again:
|
|
33
|
+
`),1}var Ht=m(()=>{"use strict";it();});function br(){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 {home:e,username:process.env.SUDO_USER}}return {home:dt__namespace.homedir(),username:process.env.SUDO_USER||process.env.USER||dt__namespace.userInfo().username}}function A(){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 Rt__namespace.join(e,".claude","settings.json")}return Rt__namespace.join(dt__namespace.homedir(),".claude","settings.json")}if(process.platform==="win32"){let t=process.env.USERPROFILE||dt__namespace.homedir();return Rt__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 Rt__namespace.join(e,".claude","settings.json")}return Rt__namespace.join(dt__namespace.homedir(),".claude","settings.json")}var fe=m(()=>{"use strict";Ht();});function me(){if(process.platform==="win32"){let r=process.env.APPDATA||Rt__namespace.join(dt__namespace.homedir(),"AppData","Roaming");return Rt__namespace.join(r,Cr,Nr)}let t=br(),e=process.env.XDG_CONFIG_HOME||Rt__namespace.join(t.home,".config");return Rt__namespace.join(e,Cr,Nr)}function Wt(){try{let t=g__namespace.readFileSync(A(),"utf8"),r=JSON.parse(t).env?.FLOW_BASE_URL;return typeof r=="string"&&r.trim()?r.trim():null}catch{return null}}function $r(){try{let t=g__namespace.readFileSync(A(),"utf8");return JSON.parse(t).env??null}catch{return null}}var Cr,Nr,Je=m(()=>{"use strict";fe();Cr="flow-ai-obs",Nr="config.json";});function Vt(){let t=dt__namespace.default.homedir();if(process.platform==="darwin")return Rt__namespace.default.join(t,"Library","Preferences",de,pe);if(process.platform==="win32"){let r=process.env.APPDATA??Rt__namespace.default.join(t,"AppData","Roaming");return Rt__namespace.default.join(r,de,pe)}let e=process.env.XDG_CONFIG_HOME??Rt__namespace.default.join(t,".config");return Rt__namespace.default.join(e,de,pe)}function qe(){try{let t=g__namespace.default.readFileSync(Vt(),"utf8");return JSON.parse(t)}catch{return {}}}function Fr(t){let e=Vt();g__namespace.default.mkdirSync(Rt__namespace.default.dirname(e),{recursive:true}),g__namespace.default.writeFileSync(e,JSON.stringify(t,null,2),{encoding:"utf8",mode:384});}var Ke,ge,xr=m(()=>{"use strict";k();Ke={credentials:"credentials","token-cache":"tokenCache"};ge=class{static isAvailable(){return !0}static hasExistingData(){try{if(!g__namespace.default.existsSync(Vt()))return !1;let e=JSON.parse(g__namespace.default.readFileSync(Vt(),"utf8"));return !!(e&&e.credentials)}catch{return !1}}async getSecret(e,r){let n=qe(),s=Ke[r]??r,o=n[s];return o?typeof o=="string"?o:JSON.stringify(o):null}async setSecret(e,r,n){let s=qe(),o=Ke[r]??r;if(r==="token-cache")try{s[o]=JSON.parse(n);}catch{s[o]=n;}else s[o]=n;Fr(s);}async deleteSecret(e,r){let n=qe(),s=Ke[r]??r;return s in n?(delete n[s],Fr(n),!0):!1}getStoragePath(){return `config.json (unencrypted) \u2014 ${Vt()}`}};});var Dr={};W(Dr,{MacOsKeyVaultProvider:()=>ze});var Xe,ze,Mr=m(()=>{"use strict";Xe=util.promisify(child_process.execFile),ze=class{static async isAvailable(){try{return g.accessSync("/usr/bin/security",g.constants.X_OK),!0}catch{return !1}}async getSecret(e,r){try{let{stdout:n}=await Xe("security",["find-generic-password","-w","-a",r,"-s",e]);return n.trim()||null}catch{return null}}async setSecret(e,r,n){await Xe("security",["add-generic-password","-U","-a",r,"-s",e,"-w",n]);}async deleteSecret(e,r){try{return await Xe("security",["delete-generic-password","-a",r,"-s",e]),!0}catch{return !1}}getStoragePath(){return "macOS Keychain"}};});var Hr={};W(Hr,{LinuxKeyVaultProvider:()=>Ze});var Br,Ze,jr=m(()=>{"use strict";Br=util.promisify(child_process.execFile),Ze=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 g.accessSync(r,g.constants.X_OK),!0}catch{}return !1}async getSecret(e,r){try{let{stdout:n}=await Br("secret-tool",["lookup","service",e,"account",r]);return n.trim()||null}catch{return null}}async setSecret(e,r,n){await new Promise((s,o)=>{let i=child_process.spawn("secret-tool",["store","--label",e,"service",e,"account",r]);i.on("error",o),i.on("close",a=>{a===0?s():o(new Error(`secret-tool exited with code ${a}`));}),i.stdin.write(n),i.stdin.end();});}async deleteSecret(e,r){try{return await Br("secret-tool",["clear","service",e,"account",r]),!0}catch{return !1}}getStoragePath(){return "Linux Secret Service (libsecret)"}};});var Wr={};W(Wr,{WindowsKeyVaultProvider:()=>Qe});var Qe,Vr=m(()=>{"use strict";Qe=class{static async isAvailable(){try{return await xt("keytar").getPassword("__flow_probe__","__flow_probe__"),!0}catch{return !1}}async getSecret(e,r){return xt("keytar").getPassword(e,r)}async setSecret(e,r,n){await xt("keytar").setPassword(e,r,n);}async deleteSecret(e,r){return xt("keytar").deletePassword(e,r)}getStoragePath(){return "Windows Credential Manager"}};});async function Yr(){return await Gs()??new ge}async function Gs(){switch(process.platform){case "darwin":{let{MacOsKeyVaultProvider:t}=await Promise.resolve().then(()=>(Mr(),Dr));return await t.isAvailable()?new t:null}case "linux":{let{LinuxKeyVaultProvider:t}=await Promise.resolve().then(()=>(jr(),Hr));return await t.isAvailable()?new t:null}case "win32":{let{WindowsKeyVaultProvider:t}=await Promise.resolve().then(()=>(Vr(),Wr));return await t.isAvailable()?new t:null}default:return null}}var Gr=m(()=>{"use strict";xr();});function qr(){return tr||(tr=Yr()),tr}async function Gt(t){await(await qr()).setSecret(Jr,Kr,JSON.stringify({accessToken:t.accessToken,expiresAt:t.expiresAt,lastAuthCheckAt:t.lastAuthCheckAt}));}async function It(){let e=await(await qr()).getSecret(Jr,Kr);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 he(){let t=await It();return t?new Date(t.expiresAt)>new Date:false}async function Jt(){let t=await It();if(!t||!t.accessToken)return null;try{let e=t.accessToken.split(".");if(e.length<2)return null;let r=JSON.parse(Buffer.from(e[1].replace(/-/g,"+").replace(/_/g,"/"),"base64").toString("utf8"));return r.email??r.preferred_username??r.upn??r.sub??null}catch{return null}}var Jr,Xi,Kr,tr,Ee=m(()=>{"use strict";Gr();k();Jr=ue.SERVICE,Xi=ue.ACCOUNT_CREDS,Kr=ue.ACCOUNT_TOKEN,tr=null;});function qs(t){return Ks.some(e=>e.test(t))}function Xs(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 B(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 Xr(t){let e=Buffer.from(JSON.stringify({alg:"none",typ:"JWT"})).toString("base64url"),r=Buffer.from(JSON.stringify({clientId:t.clientId,clientSecret:t.clientSecret,tenant:t.tenant})).toString("base64url");return `${e}.${r}.`}function pt(t){let e;try{e=new URL(t);}catch{throw new Error(`Invalid URL: ${t}`)}let r=process.env[p.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&&qs(e.hostname))throw new Error(`SSRF: private/loopback host not allowed: ${e.hostname}`);return t}async function zr(){let t=B(process.env[p.ANTHROPIC_AUTH_TOKEN]);return t?{user:await Jt().catch(()=>null)??t.clientId,tenant:t.tenant}:{user:"",tenant:""}}function zs(){return new Date().toISOString().slice(0,10)}async function Zs(t){let e=zs(),r=await It();if(r?.lastAuthCheckAt!==e){l("getOrRefreshToken",`daily auth check (last: ${r?.lastAuthCheckAt??"never"})`);try{let o=await q(t);try{await Gt({...o,lastAuthCheckAt:e});}catch{}return l("getOrRefreshToken",`daily check passed, expires=${o.expiresAt}`),o.accessToken}catch(o){if(o instanceof lt)throw o;l("getOrRefreshToken",`daily check network error \u2014 using cache: ${o.message}`);}}let n=r!=null&&new Date(r.expiresAt)>new Date;if(l("getOrRefreshToken",`cacheValid=${n}`),n)return l("getOrRefreshToken",`using cached token, expires=${r.expiresAt}`),r.accessToken;l("getOrRefreshToken",`token expired \u2014 refreshing via auth-engine (tenant=${t.tenant} clientId=${t.clientId})`);let s=await q(t);try{await Gt({...s,lastAuthCheckAt:e});}catch(o){l("getOrRefreshToken",`token cache save failed (non-fatal): ${o.message}`);}return l("getOrRefreshToken",`token refreshed, expires=${s.expiresAt}`),s.accessToken}function Qs(t,e){let r=e&&e.accessToken?e.accessToken:"";return {endpoint:t.replace(/\/$/,"")+"/flow-langfuse-gateway/v1/traces",authHeader:`Bearer ${r}`}}function to(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 J(){let t=[],e=process.env[p.ANTHROPIC_MODEL]??"",r=B(process.env[p.ANTHROPIC_AUTH_TOKEN]);l("resolveCredentials",r?"credentials resolved from ANTHROPIC_AUTH_TOKEN":"ANTHROPIC_AUTH_TOKEN absent or invalid"),r&&l("resolveCredentials",`clientId=${r.clientId}`,`tenant=${r.tenant}`);let n=r?r.tenant:"",s=process.env[p.FLOW_TELEMETRY]==="true",o=process.env[p.LANGFUSE_BASE_URL],i=process.env[p.LANGFUSE_PUBLIC_KEY],a=process.env[p.LANGFUSE_SECRET_KEY];if(s&&o&&i&&a){let E="",S=n;r&&(E=await Jt().catch(()=>null)??r.clientId);let v={user:E??"",tenant:S??"",team:"",project:"",model:e};t.push({mode:"direct",...to(pt(o),i,a),...v}),l("resolveCredentials","direct mode active",`user=${v.user}`,`tenant=${v.tenant}`);}if(!r){if(t.length===0){let E=[];return E.authError=false,E}return t}let c;try{c=await Zs(r);}catch(E){if(l("resolveCredentials",`token refresh failed: ${E.message}`,`(tenant=${r.tenant} clientId=${r.clientId})`),t.length>0)return t.authError=true,t;let S=[];return S.authError=true,S}let d={user:Xs(c)??r.clientId,tenant:n,team:"",project:"",model:e},h=process.env[p.FLOW_TELEMETRY_GATEWAY]??ct();return t.push({mode:"gateway",...Qs(pt(h),{accessToken:c}),...d}),t}async function Zr(){return (await J()).length>0}function ft(){let t=process.env[p.FLOW_USER_EMAIL];if(t)return l("resolveUserEmail",`using FLOW_USER_EMAIL override: ${t}`),t;try{let e=dt__namespace.default.userInfo().username||process.env.USERNAME||process.env.USER||"",r=e.lastIndexOf("\\");if(r!==-1&&(e=e.slice(r+1)),e=e.trim().replace(/[^a-zA-Z0-9._%+\-]/g,""),!e)return l("resolveUserEmail","username empty after sanitisation \u2014 omitting x-flow-user"),console.warn("[flow-ai-obs] Could not derive x-flow-user: username is empty. Set FLOW_USER_EMAIL to fix this."),null;let n=`${e}@ciandt.com`;return l("resolveUserEmail",`derived email: ${n}`),n}catch(e){return l("resolveUserEmail",`os.userInfo() threw: ${e.message} \u2014 omitting x-flow-user`),console.warn("[flow-ai-obs] Could not derive x-flow-user from OS username. Set FLOW_USER_EMAIL to fix this."),null}}var Ks,N=m(()=>{"use strict";Ee();Bt();k();M();Ks=[/^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 we(t){try{let e=g__namespace.statSync(t);Date.now()-e.mtimeMs>eo&&g__namespace.unlinkSync(t);}catch{}try{g__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 Se(t){try{g__namespace.unlinkSync(t);}catch{}}function Qr(t,e){let n=(Array.isArray(t)?t:[]).map(s=>{if(!Array.isArray(s?.hooks))return null;let o=s.hooks.filter(i=>!i.command?.startsWith?.("flow-ai-obs "));return o.length>0?{...s,hooks:o}:null}).filter(s=>s!=null);return [e,...n]}function tn(){let t=A(),e=t+".lock",r=[];g__namespace.mkdirSync(Rt__namespace.dirname(t),{recursive:true}),we(e);try{if(g__namespace.existsSync(t)){g__namespace.copyFileSync(t,t+".bkp");try{g__namespace.chmodSync(t+".bkp",384);}catch{}}let n=me();if(g__namespace.existsSync(n)){let u=n+".bkp";g__namespace.copyFileSync(n,u);try{g__namespace.chmodSync(u,384);}catch{}}let s={};try{s=JSON.parse(g__namespace.readFileSync(t,"utf8"));}catch{}let o=s.env&&typeof s.env=="object"?s.env:{};delete o.OTEL_EXPORTER_OTLP_HEADERS,s.env={...o,...V,...Mt()},s.otelHeadersHelper="flow-ai-obs otel-headers",(!s.hooks||typeof s.hooks!="object"||Array.isArray(s.hooks))&&(s.hooks={});let i=(u,d)=>({matcher:"",hooks:[{type:"command",command:`flow-ai-obs ${u}`,timeout:d}]}),a=["UserPromptSubmit","PreToolUse","PostToolUse","Stop"],c=s.hooks;for(let u of a){let d=Qr(c[u],i(u,We[u]));d.length>1&&r.push(u),c[u]=d;}g__namespace.writeFileSync(t,JSON.stringify(s,null,2)+`
|
|
34
|
+
`,{encoding:"utf8",mode:384});try{g__namespace.chmodSync(t,384);}catch{}}finally{Se(e);}return {settingsPath:t,preserved:r}}function Pt(t){try{let e=g__namespace.readFileSync(A(),"utf8"),n=JSON.parse(e).env?.[t];return typeof n=="string"?n:null}catch{return null}}function H(t){let e=A(),r=e+".lock";g__namespace.mkdirSync(Rt__namespace.dirname(e),{recursive:true}),we(r);try{let n={};try{n=JSON.parse(g__namespace.readFileSync(e,"utf8"));}catch{}(!n.env||typeof n.env!="object")&&(n.env={}),Object.assign(n.env,t),g__namespace.writeFileSync(e,JSON.stringify(n,null,2)+`
|
|
35
|
+
`,{encoding:"utf8",mode:384});try{g__namespace.chmodSync(e,384);}catch{}}finally{Se(r);}}function en(){let t=A(),e=t+".lock",r=[];g__namespace.mkdirSync(Rt__namespace.dirname(t),{recursive:true}),we(e);try{if(g__namespace.existsSync(t)){g__namespace.copyFileSync(t,t+".bkp");try{g__namespace.chmodSync(t+".bkp",384);}catch{}}let n={};try{n=JSON.parse(g__namespace.readFileSync(t,"utf8"));}catch{}n.otelHeadersHelper="flow-ai-obs otel-headers",(!n.hooks||typeof n.hooks!="object"||Array.isArray(n.hooks))&&(n.hooks={});let s=(a,c)=>({matcher:"",hooks:[{type:"command",command:`flow-ai-obs ${a}`,timeout:c}]}),o=["UserPromptSubmit","PreToolUse","PostToolUse","Stop"],i=n.hooks;for(let a of o){let c=Qr(i[a],s(a,We[a]));c.length>1&&r.push(a),i[a]=c;}g__namespace.writeFileSync(t,JSON.stringify(n,null,2)+`
|
|
36
|
+
`,{encoding:"utf8",mode:384});try{g__namespace.chmodSync(t,384);}catch{}}finally{Se(e);}return {settingsPath:t,preserved:r}}function rn(t){let e=A(),r=e+".lock";g__namespace.mkdirSync(Rt__namespace.dirname(e),{recursive:true}),we(r);try{let n={};try{n=JSON.parse(g__namespace.readFileSync(e,"utf8"));}catch{return}if(!n.env||typeof n.env!="object")return;for(let s of t)delete n.env[s];g__namespace.writeFileSync(e,JSON.stringify(n,null,2)+`
|
|
37
|
+
`,{encoding:"utf8",mode:384});try{g__namespace.chmodSync(e,384);}catch{}}finally{Se(r);}}var eo,qt=m(()=>{"use strict";k();Bt();fe();Je();N();eo=Lr.LOCK_STALE_MS;});function Te(){if(process.env.WSL_DISTRO_NAME&&process.platform==="linux")return child_process.spawnSync("cmd.exe",["/c","where","claude"],{encoding:"utf8",timeout:5e3}).status===0;let t=process.platform==="win32"?"where":"which";return child_process.spawnSync(t,["claude"],{encoding:"utf8",timeout:5e3}).status===0}function rr(){try{if(process.env.WSL_DISTRO_NAME&&process.platform==="linux"){let e=child_process.spawnSync("cmd.exe",["/c","claude","--version"],{encoding:"utf8",timeout:5e3});return e.status===0?e.stdout.trim():null}let t=child_process.spawnSync("claude",["--version"],{encoding:"utf8",timeout:5e3});return t.status===0?t.stdout.trim():null}catch{return null}}function nn(){if(child_process.spawnSync("node",["--version"],{encoding:"utf8",timeout:5e3}).status!==0)return {success:false,error:"no_nodejs",message:`Node.js is not installed. Install Node.js 18+ and try again:
|
|
38
38
|
${{darwin:`brew install node
|
|
39
39
|
or download from: https://nodejs.org`,win32:`winget install OpenJS.NodeJS
|
|
40
|
-
or download from: https://nodejs.org`,linux:"See package manager instructions at: https://nodejs.org/en/download/package-manager"}[process.platform]??"Download from: https://nodejs.org"}`};let e=child_process.spawnSync("npm",["install","-g",
|
|
41
|
-
npm install -g ${
|
|
42
|
-
sudo npm install -g ${
|
|
43
|
-
`){
|
|
44
|
-
`),r(i);return}if(
|
|
45
|
-
|
|
46
|
-
`)),0}catch(e){return process.stderr.write(
|
|
47
|
-
`)),1}}async function
|
|
48
|
-
`);let t=(await X(I(" ? ")+"Client ID: ")).trim(),e=(await X(I(" ? ")+"Client Secret: ",{masked:!0})).trim(),r=(await X(I(" ? ")+"Tenant: ")).trim();if(!t||!e||!r)return process.stderr.write(
|
|
49
|
-
`)),1;try{await
|
|
50
|
-
`)),1}return process.stdout.write(
|
|
51
|
-
`)),process.stdout.write(` Storage:
|
|
52
|
-
|
|
53
|
-
`),0}catch(t){if(t.message==="SIGINT"||t.message==="NOT_A_TTY")throw t;return process.stderr.write(
|
|
54
|
-
`)),1}}async function mt(t={}){let e=
|
|
55
|
-
`),process.stdout.write(
|
|
56
|
-
`)),process.stdout.write(
|
|
57
|
-
`),process.stdout.write(
|
|
40
|
+
or download from: https://nodejs.org`,linux:"See package manager instructions at: https://nodejs.org/en/download/package-manager"}[process.platform]??"Download from: https://nodejs.org"}`};let e=child_process.spawnSync("npm",["install","-g",er],{encoding:"utf8",stdio:["inherit","inherit","pipe"],timeout:12e4});if(e.status===0)return {success:true};let r=String(e.stderr??""),n=e.error,s=n instanceof Error?n.message:r;return s.includes("EACCES")||s.includes("permission denied")||s.includes("EPERM")||r.includes("EACCES")||r.includes("EPERM")?{success:false,error:"permission_denied",message:process.platform==="win32"?`Run this terminal as Administrator and try again:
|
|
41
|
+
npm install -g ${er}`:`Try with elevated permissions:
|
|
42
|
+
sudo npm install -g ${er}`}:{success:false,error:"unknown",message:s||"npm install failed"}}var er,nr=m(()=>{"use strict";er="@anthropic-ai/claude-code";});function sr(){return Rt__namespace.default.join(dt__namespace.default.homedir(),".claude","flow-obs",".logged-out")}function on(){try{let t=sr();g__namespace.default.mkdirSync(Rt__namespace.default.dirname(t),{recursive:!0}),g__namespace.default.writeFileSync(t,"",{mode:384});}catch{}}function an(){try{g__namespace.default.unlinkSync(sr());}catch{}}function or(){try{return g__namespace.default.existsSync(sr())}catch{return false}}var cn=m(()=>{"use strict";});var ir={};W(ir,{promptRaw:()=>X,runLogin:()=>mt,runLogout:()=>ao,runStatus:()=>co});function z(t){return typeof t=="string"?t.replace(no,""):t}function X(t,e={}){return new Promise((r,n)=>{if(typeof process.stdin.setRawMode!="function"){n(new Error("NOT_A_TTY"));return}let{masked:s=false,defaultValue:o=""}=e;process.stdout.write(t+o);let i=o;function a(){try{process.stdin.setRawMode(!1);}catch{}}process.once("uncaughtException",a),process.once("unhandledRejection",a);let c=d=>{if(d===""){u(),n(new Error("SIGINT"));return}if(d==="\r"||d===`
|
|
43
|
+
`){u(),process.stdout.write(`
|
|
44
|
+
`),r(i);return}if(d==="\x7F"){i.length>0&&(i=i.slice(0,-1),process.stdout.write("\b \b"));return}d.startsWith("\x1B")||(i+=d,process.stdout.write(s?"*".repeat(d.length):d));};function u(){process.stdin.setRawMode(false),process.stdin.removeListener("data",c),process.removeListener("uncaughtException",a),process.removeListener("unhandledRejection",a);}process.stdin.setRawMode(true),process.stdin.resume(),process.stdin.setEncoding("utf8"),process.stdin.on("data",c);})}async function ln(t){let{accessToken:e,expiresAt:r}=await q(t),n=Xr(t);H({[p.ANTHROPIC_AUTH_TOKEN]:n}),an(),await Gt({accessToken:e,expiresAt:r});}async function so(t){try{return await ln(t),process.stdout.write(L(` \u2713 Setup complete. Tenant: ${z(t.tenant)}
|
|
45
|
+
|
|
46
|
+
`)),0}catch(e){return process.stderr.write(R(` \u2717 Authentication failed: ${z(e.message)}
|
|
47
|
+
`)),1}}async function oo(){try{process.stdout.write(`
|
|
48
|
+
`);let t=(await X(I(" ? ")+"Client ID: ")).trim(),e=(await X(I(" ? ")+"Client Secret: ",{masked:!0})).trim(),r=(await X(I(" ? ")+"Tenant: ")).trim();if(!t||!e||!r)return process.stderr.write(R(` \u2717 All fields are required
|
|
49
|
+
`)),1;try{await ln({clientId:t,clientSecret:e,tenant:r});}catch(n){return process.stderr.write(R(` \u2717 Authentication failed: ${z(n.message)}
|
|
50
|
+
`)),1}return process.stdout.write(L(` \u2713 Setup complete. Tenant: ${z(r)}
|
|
51
|
+
`)),process.stdout.write(` Storage: ANTHROPIC_AUTH_TOKEN (settings.json)
|
|
52
|
+
|
|
53
|
+
`),0}catch(t){if(t.message==="SIGINT"||t.message==="NOT_A_TTY")throw t;return process.stderr.write(R(` \u2717 Unexpected error: ${t.message}
|
|
54
|
+
`)),1}}async function mt(t={}){let e=ut();if(e)return e;if(t.clientId&&t.clientSecret&&t.tenant)return so({clientId:t.clientId,clientSecret:t.clientSecret,tenant:t.tenant});let n=or()?null:B(Pt(p.ANTHROPIC_AUTH_TOKEN)??process.env[p.ANTHROPIC_AUTH_TOKEN]);if(n){process.stdout.write(`
|
|
55
|
+
`),process.stdout.write(b(` Already authenticated
|
|
56
|
+
`)),process.stdout.write(w(" Tenant: ")+z(n.tenant)+`
|
|
57
|
+
`),process.stdout.write(w(" Client ID: ")+z(n.clientId)+`
|
|
58
58
|
`),process.stdout.write(`
|
|
59
59
|
`);let s;try{s=await X(I(" ? ")+"Re-authenticate? (y/N): ");}catch(o){if(o.message==="SIGINT")return process.stdout.write(`
|
|
60
|
-
`),130;if(o.message==="NOT_A_TTY")return process.stdout.write(
|
|
60
|
+
`),130;if(o.message==="NOT_A_TTY")return process.stdout.write(L(` \u2713 Using existing credentials.
|
|
61
61
|
|
|
62
|
-
`)),0;throw o}if(s.trim().toLowerCase()!=="y")return process.stdout.write(
|
|
62
|
+
`)),0;throw o}if(s.trim().toLowerCase()!=="y")return process.stdout.write(L(` \u2713 Using existing credentials.
|
|
63
63
|
|
|
64
|
-
`)),0}try{return await
|
|
65
|
-
`),130;if(s.message==="NOT_A_TTY")return process.stderr.write(
|
|
66
|
-
`)+" Pass --client-id, --client-secret and --tenant, or run `flow-ai-obs auth login` in a terminal.\n\n"),1;throw s}}async function
|
|
67
|
-
`),(await X(I(" ? ")+"Are you sure? This will remove your local credentials. (y/N): ")).toLowerCase()!=="y"?(process.stdout.write(
|
|
64
|
+
`)),0}try{return await oo()}catch(s){if(s.message==="SIGINT")return process.stdout.write(`
|
|
65
|
+
`),130;if(s.message==="NOT_A_TTY")return process.stderr.write(R(` \u2717 No credentials found and no TTY available for interactive login.
|
|
66
|
+
`)+" Pass --client-id, --client-secret and --tenant, or run `flow-ai-obs auth login` in a terminal.\n\n"),1;throw s}}async function io(){try{return process.stdout.write(`
|
|
67
|
+
`),(await X(I(" ? ")+"Are you sure? This will remove your local credentials. (y/N): ")).toLowerCase()!=="y"?(process.stdout.write(_(` \u26A0 Logout cancelled
|
|
68
68
|
`)),0):null}catch(t){if(t.message==="SIGINT")return process.stdout.write(`
|
|
69
|
-
`),130;throw t}}async function
|
|
70
|
-
`)),0;if(!t){let
|
|
71
|
-
`)),0}catch{return process.stderr.write(
|
|
72
|
-
`)),1}}async function
|
|
73
|
-
`+
|
|
74
|
-
`)),process.stdout.write(
|
|
75
|
-
`),process.stdout.write(
|
|
76
|
-
`),process.stdout.write(
|
|
77
|
-
`),process.stdout.write(
|
|
78
|
-
|
|
79
|
-
`),0}var
|
|
69
|
+
`),130;throw t}}async function ao(t=false){let e=ut();if(e)return e;if(!B(Pt(p.ANTHROPIC_AUTH_TOKEN)??process.env[p.ANTHROPIC_AUTH_TOKEN]))return process.stdout.write(_(` \u26A0 You are not authenticated
|
|
70
|
+
`)),0;if(!t){let n=await io();if(n!==null)return n}try{return rn([p.ANTHROPIC_AUTH_TOKEN]),delete process.env[p.ANTHROPIC_AUTH_TOKEN],on(),process.stdout.write(L(` \u2713 Credentials removed successfully
|
|
71
|
+
`)),0}catch{return process.stderr.write(R(` \u2717 Error removing credentials
|
|
72
|
+
`)),1}}async function co(){if(or())return process.stdout.write(_(" \u26A0 Not authenticated. Run `flow-ai-obs auth login` to set up.\n")),0;let t=B(Pt(p.ANTHROPIC_AUTH_TOKEN)??process.env[p.ANTHROPIC_AUTH_TOKEN]);if(!t)return process.stdout.write(_(" \u26A0 Not authenticated. Run `flow-ai-obs auth login` to set up.\n")),0;if(!await he())return process.stdout.write(_(" \u26A0 Session expired. Run `flow-ai-obs auth login` to re-authenticate.\n")),0;let e=t.clientSecret.length>4?"****...****"+t.clientSecret.slice(-4):"****";return process.stdout.write(`
|
|
73
|
+
`+b(` Authenticated
|
|
74
|
+
`)),process.stdout.write(w(" Tenant: ")+z(t.tenant)+`
|
|
75
|
+
`),process.stdout.write(w(" Client ID: ")+z(t.clientId)+`
|
|
76
|
+
`),process.stdout.write(w(" Client Secret: ")+e+`
|
|
77
|
+
`),process.stdout.write(w(" Storage: ")+`ANTHROPIC_AUTH_TOKEN (settings.json)
|
|
78
|
+
|
|
79
|
+
`),0}var no,Xt=m(()=>{"use strict";Ee();cn();Bt();N();qt();k();it();Ht();no=/[\x00-\x08\x0B-\x1F\x7F]|\x1b\[[0-9;]*[a-zA-Z]/g;});var cr={};W(cr,{normalizeCustomUrl:()=>pn,runInit:()=>fo,validateCustomUrl:()=>ar});function lo(){try{let t=g__namespace.readFileSync(A(),"utf8"),e=JSON.parse(t);return !!(e.env&&e.env[p.ANTHROPIC_AUTH_TOKEN])}catch{return false}}function uo(){let t=Wt();if(!t)return null;H({FLOW_BASE_URL:t});try{let e=me(),r={};try{r=JSON.parse(g__namespace.readFileSync(e,"utf8"));}catch{return t}delete r.baseUrl,Object.keys(r).length===0?g__namespace.unlinkSync(e):g__namespace.writeFileSync(e,JSON.stringify(r,null,2)+`
|
|
80
|
+
`,{encoding:"utf8",mode:384});}catch{}return t}function pn(t){let e=t.trim().replace(/\\/g,"/");/^https?:\/\//i.test(e)||(e=`https://${e}`);try{let r=new URL(e);return `${r.protocol}//${r.host}`}catch{return e}}function ar(t,e=false){if(e){let o;try{o=new URL(t);}catch{throw new Error(`Invalid URL: ${t}`)}if(o.protocol!=="https:")throw new Error(`Custom URL must use HTTPS: ${t}`);if(o.pathname!=="/"&&o.pathname!=="")throw new Error(`Custom URL must be a base URL with no path beyond the root.
|
|
80
81
|
Received: ${t}
|
|
81
|
-
Expected: https://tenant.example.com`);if(
|
|
82
|
+
Expected: https://tenant.example.com`);if(o.search)throw new Error(`Custom URL must not contain query parameters.
|
|
82
83
|
Received: ${t}
|
|
83
|
-
Expected: https://tenant.example.com`);if(
|
|
84
|
+
Expected: https://tenant.example.com`);if(o.hash)throw new Error(`Custom URL must not contain a fragment.
|
|
84
85
|
Received: ${t}
|
|
85
|
-
Expected: https://tenant.example.com`);return t.replace(/\/$/,"")}async function
|
|
86
|
+
Expected: https://tenant.example.com`);let i=process.env[p.FLOW_OBS_ALLOW_HTTP];try{delete process.env[p.FLOW_OBS_ALLOW_HTTP],pt(t);}finally{i!==void 0&&(process.env[p.FLOW_OBS_ALLOW_HTTP]=i);}return t.replace(/\/$/,"")}let r=pn(t),n;try{n=new URL(r);}catch{throw new Error(`Invalid URL: ${t}`)}if(n.protocol!=="https:")throw new Error(`Custom URL must use HTTPS: ${t}`);if(!n.hostname.includes("."))throw new Error(`Invalid domain: ${n.hostname}. Expected format: tenant.example.com`);let s=process.env[p.FLOW_OBS_ALLOW_HTTP];try{delete process.env[p.FLOW_OBS_ALLOW_HTTP],pt(r);}finally{s!==void 0&&(process.env[p.FLOW_OBS_ALLOW_HTTP]=s);}return r.replace(/\/$/,"")}async function un(){for(let t=1;t<=3;t++)try{let e=await le(" Enter your Flow domain (e.g., tenant.ciandt.com)");return ar(e)}catch(e){if(process.stderr.write(_(` \u2717 ${e.message}
|
|
86
87
|
|
|
87
|
-
`)),t===3)throw process.stderr.write(
|
|
88
|
+
`)),t===3)throw process.stderr.write(R(` Too many invalid attempts.
|
|
88
89
|
|
|
89
|
-
`)),new Error("Too many invalid URL attempts")}throw new Error("Too many invalid URL attempts")}async function
|
|
90
|
-
`)+(r?
|
|
91
|
-
`):
|
|
92
|
-
`)));return}if(!r){process.stdout.write(
|
|
90
|
+
`)),new Error("Too many invalid URL attempts")}throw new Error("Too many invalid URL attempts")}async function po(t,e){let r=ft(),n=r??"(could not be derived)";if(!t||!at()){process.stdout.write(w(` e-mail: ${n}
|
|
91
|
+
`)+(r?w(` To use a different email, set FLOW_USER_EMAIL in ~/.claude/settings.json env block.
|
|
92
|
+
`):_(` Could not derive your email. Set FLOW_USER_EMAIL before running hooks.
|
|
93
|
+
`)));return}if(!r){process.stdout.write(_(`
|
|
93
94
|
\u26A0 Could not derive email from OS username.
|
|
94
|
-
`));let s=await
|
|
95
|
+
`));let s=await le(" Enter your corporate email",o=>o.includes("@")?null:"Email must contain @");H({[p.FLOW_USER_EMAIL]:s}),process.stdout.write(L(` \u2713 Email saved: ${s}
|
|
95
96
|
|
|
96
|
-
`));return}if(e)if(await
|
|
97
|
+
`));return}if(e)if(await ce(" Is your corporate email domain @ciandt.com?",true))process.stdout.write(L(` \u2713 Email: ${b(n)}
|
|
97
98
|
|
|
98
|
-
`));else {let o=await
|
|
99
|
+
`));else {let o=await le(" Enter your corporate email",i=>i.includes("@")?null:"Email must contain @");H({[p.FLOW_USER_EMAIL]:o}),process.stdout.write(L(` \u2713 Email saved: ${o}
|
|
99
100
|
|
|
100
|
-
`));}else process.stdout.write(
|
|
101
|
+
`));}else process.stdout.write(L(` \u2713 Email: ${b(n)}
|
|
101
102
|
|
|
102
|
-
`));}async function
|
|
103
|
-
`+
|
|
103
|
+
`));}function dn(){try{let t=g__namespace.readFileSync(A(),"utf8"),r=JSON.parse(t).env?.FLOW_BASE_URL;return typeof r=="string"&&r.trim()?r.trim():null}catch{return null}}async function fo(t={}){let e=ut();if(e)return e;let r=t.url;if(!Te())return process.stderr.write(`
|
|
104
|
+
`+R(` \u2717 Claude Code is not installed or not found in PATH.
|
|
104
105
|
|
|
105
106
|
`)+` flow-ai-obs requires Claude Code to function.
|
|
106
107
|
Install it with:
|
|
107
108
|
|
|
108
109
|
`+I(" npm install -g @anthropic-ai/claude-code")+`
|
|
109
110
|
|
|
110
|
-
`),1;
|
|
111
|
-
`)+
|
|
112
|
-
`)+
|
|
113
|
-
|
|
114
|
-
`))
|
|
115
|
-
|
|
116
|
-
`)
|
|
117
|
-
|
|
118
|
-
`)
|
|
119
|
-
|
|
120
|
-
`)
|
|
111
|
+
`),1;process.env.WSL_DISTRO_NAME&&process.platform==="linux"&&process.stdout.write(_(` \u26A0 WSL detected. If Claude Code is installed on Windows, install flow-ai-obs
|
|
112
|
+
`)+_(" on Windows too: ")+I(`npm install -g @ciandt-flow/flow-ai-obs
|
|
113
|
+
`)+_(` Running Claude (Windows) + flow-ai-obs (WSL) is not a supported configuration.
|
|
114
|
+
|
|
115
|
+
`));let n=uo();if(n&&process.stdout.write(_(` \u26A0 Legacy config migrated.
|
|
116
|
+
`)+w(` Custom URL moved from ~/.config/flow-ai-obs/config.json
|
|
117
|
+
`)+w(` to FLOW_BASE_URL in ~/.claude/settings.json: ${n}
|
|
118
|
+
|
|
119
|
+
`)),!r&&!t.noInteractive&&at()){let d=dn();try{d?(process.stdout.write(`
|
|
120
|
+
Current base URL: ${b(d)}
|
|
121
|
+
`),await ce(" Keep this URL?",!0)||(r=await un())):(process.stdout.write(`
|
|
122
|
+
`),await ce(" Does your organization use a custom Flow URL?",!1)&&(r=await un()));}catch{return 1}process.stdout.write(`
|
|
123
|
+
`);}if(!r&&!t.noInteractive&&!at()){let d=dn(),h=process.env.FLOW_BASE_URL,E=d??h??Dt,S=!!(d??h);process.stdout.write(_(` \u26A0 Non-interactive environment detected.
|
|
124
|
+
`)+w(` Using URL: ${E}
|
|
125
|
+
`)+(S?"":w(` Run with --custom-url to configure a custom domain.
|
|
121
126
|
`))+`
|
|
122
|
-
`);}await
|
|
123
|
-
\u2717 Invalid --custom-url: ${
|
|
127
|
+
`);}await po(!t.noInteractive,!!(r??Wt()));let s=null,o=null;if(r){let d;try{d=ar(r,!0);}catch(Tt){return process.stderr.write(`
|
|
128
|
+
\u2717 Invalid --custom-url: ${Tt.message}
|
|
124
129
|
|
|
125
|
-
`),1}let
|
|
126
|
-
|
|
130
|
+
`),1}let h=Wt(),E=$r(),S=`${d}/otel`,v=`${d}/flow-llm-proxy/`,O=h??Dt,St=E?.OTEL_EXPORTER_OTLP_ENDPOINT&&E.OTEL_EXPORTER_OTLP_ENDPOINT!==`${O}/otel`,nt=E?.ANTHROPIC_BASE_URL&&E.ANTHROPIC_BASE_URL!==`${O}/flow-llm-proxy/`;o={FLOW_BASE_URL:d,OTEL_EXPORTER_OTLP_ENDPOINT:St?E.OTEL_EXPORTER_OTLP_ENDPOINT:S,ANTHROPIC_BASE_URL:nt?E.ANTHROPIC_BASE_URL:v},s=d,h&&h!==d?process.stdout.write(_(` \u26A0 Base URL updated.
|
|
131
|
+
`)+w(` Previous: ${h}
|
|
132
|
+
`)+w(` New: ${d}
|
|
127
133
|
|
|
128
|
-
`)
|
|
129
|
-
`)+g(` Previous: ${p}
|
|
130
|
-
`)+g(` New: ${l}
|
|
134
|
+
`)):process.stdout.write(L(` \u2713 Base URL configured: ${d}
|
|
131
135
|
|
|
132
|
-
`))
|
|
136
|
+
`));}if(!lo())if(t.noInteractive||!at())process.stdout.write(_(" \u26A0 No credentials found in settings.json \u2014 run `flow-ai-obs auth login` to authenticate.\n\n"));else {process.stdout.write(_(` \u26A0 No credentials found in settings.json \u2014 authentication required.
|
|
133
137
|
|
|
134
|
-
`));}
|
|
135
|
-
|
|
136
|
-
`));let{runLogin:l}=await Promise.resolve().then(()=>(qt(),ur)),p=await l();if(p!==0)return p}let o,i;try{(({settingsPath:o,preserved:i}=rn())),s&&K(s);}catch(l){return process.stderr.write(` \u2717 Failed to write settings: ${l.message}
|
|
138
|
+
`));let{runLogin:d}=await Promise.resolve().then(()=>(Xt(),ir)),h=await d();if(h!==0)return h}let i,a;try{(({settingsPath:i,preserved:a}=tn())),o&&H(o);}catch(d){return process.stderr.write(` \u2717 Failed to write settings: ${d.message}
|
|
137
139
|
`),1}process.stdout.write(`
|
|
138
|
-
`+
|
|
139
|
-
`);let
|
|
140
|
+
`+b(" Native OTEL configured")+` (metrics & logs)
|
|
141
|
+
`);let c=o?{...V,OTEL_EXPORTER_OTLP_ENDPOINT:o.OTEL_EXPORTER_OTLP_ENDPOINT}:V;for(let[d,h]of Object.entries(c))process.stdout.write(w(` ${d.padEnd(36)}`)+h+`
|
|
140
142
|
`);process.stdout.write(`
|
|
141
|
-
`),process.stdout.write(
|
|
142
|
-
`),process.stdout.write(
|
|
143
|
-
`),process.stdout.write(
|
|
144
|
-
`),process.stdout.write(
|
|
145
|
-
`),process.stdout.write(
|
|
146
|
-
`),
|
|
147
|
-
`),process.stdout.write(
|
|
148
|
-
`)),process.stdout.write(
|
|
143
|
+
`),process.stdout.write(b(" Hooks registered")+` (Langfuse trace capture)
|
|
144
|
+
`),process.stdout.write(w(" UserPromptSubmit")+` \u2192 flow-ai-obs UserPromptSubmit (timeout: 5s)
|
|
145
|
+
`),process.stdout.write(w(" PreToolUse ")+` \u2192 flow-ai-obs PreToolUse (timeout: 3s)
|
|
146
|
+
`),process.stdout.write(w(" PostToolUse ")+` \u2192 flow-ai-obs PostToolUse (timeout: 10s)
|
|
147
|
+
`),process.stdout.write(w(" Stop ")+` \u2192 flow-ai-obs Stop (timeout: 15s)
|
|
148
|
+
`),a.length>0&&(process.stdout.write(`
|
|
149
|
+
`),process.stdout.write(_(` \u26A0 Third-party hooks detected and preserved on: ${a.join(", ")}
|
|
150
|
+
`)),process.stdout.write(w(` flow-ai-obs was prepended \u2014 it executes first.
|
|
149
151
|
`))),process.stdout.write(`
|
|
150
|
-
`),process.stdout.write(
|
|
151
|
-
`),process.stdout.write(
|
|
152
|
-
`),process.stdout.write(
|
|
153
|
-
`));let
|
|
152
|
+
`),process.stdout.write(w(" Settings: ")+i+`
|
|
153
|
+
`),process.stdout.write(w(" Backup: ")+i+`.bkp
|
|
154
|
+
`),process.stdout.write(w(" OTEL auth: flow-ai-obs otel-headers")+w(` (reads ANTHROPIC_AUTH_TOKEN from settings.json)
|
|
155
|
+
`));let u=s??Wt()??process.env.FLOW_BASE_URL??Dt;return process.stdout.write(w(" Base URL: ")+u+`
|
|
154
156
|
`),process.stdout.write(`
|
|
155
|
-
`),t.skipHint||(process.stdout.write(
|
|
156
|
-
`)),process.stdout.write(
|
|
157
|
-
${
|
|
158
|
-
`);}function
|
|
159
|
-
`));}function
|
|
160
|
-
`));}function zt(t){process.stderr.write(
|
|
161
|
-
`));}function gt(t){process.stdout.write(
|
|
162
|
-
`));}async function
|
|
157
|
+
`),t.skipHint||(process.stdout.write(L(` \u2713 Ready. Native OTEL + Langfuse trace capture active.
|
|
158
|
+
`)),process.stdout.write(w(" Run `flow-ai-obs setup` to configure a full environment from scratch.\n\n"))),0}var lr=m(()=>{"use strict";qt();k();it();fe();Ht();N();Je();nr();Ue();});var gn={};W(gn,{runSetup:()=>So});function mo(){try{return JSON.parse(g__namespace.readFileSync(A(),"utf8"))}catch{return {}}}function go(t){return !!(t.env??{}).ANTHROPIC_BASE_URL}function ho(t){let e=t.env??{};return Object.keys(V).every(r=>!!e[r])}function Eo(t){let e=t.hooks??{};return ["UserPromptSubmit","PreToolUse","PostToolUse","Stop"].every(n=>{let s=e[n];return Array.isArray(s)?s.some(o=>{let i=o;return Array.isArray(i?.hooks)&&i.hooks.some(a=>a?.command?.startsWith("flow-ai-obs "))}):false})}async function wo(t){return (await X(t)).trim().toLowerCase()==="y"}function _e(t,e,r){process.stdout.write(`
|
|
159
|
+
${b(`[${t}/${e}]`)} ${r}
|
|
160
|
+
`);}function K(t){process.stdout.write(L(` \u2713 ${t}
|
|
161
|
+
`));}function fn(t){process.stdout.write(_(` \u26A0 ${t}
|
|
162
|
+
`));}function zt(t){process.stderr.write(R(` \u2717 ${t}
|
|
163
|
+
`));}function gt(t){process.stdout.write(w(` ${t}
|
|
164
|
+
`));}async function So(t={}){let e=ut();if(e)return e;let r=4;process.stdout.write(`
|
|
163
165
|
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
164
166
|
`),process.stdout.write(`\u2551 flow-ai-obs \u2014 setup \u2551
|
|
165
167
|
`),process.stdout.write(`\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
166
168
|
`),process.stdout.write(`
|
|
167
169
|
This will configure your development environment:
|
|
168
|
-
`),process.stdout.write(
|
|
169
|
-
`)),process.stdout.write(
|
|
170
|
-
`)),process.stdout.write(
|
|
171
|
-
`)),process.stdout.write(
|
|
170
|
+
`),process.stdout.write(w(` [1/4] Claude Code Install @anthropic-ai/claude-code (if needed)
|
|
171
|
+
`)),process.stdout.write(w(` [2/4] Proxy Configure Flow LLM routing
|
|
172
|
+
`)),process.stdout.write(w(` [3/4] AI Usage Enable native OTEL telemetry
|
|
173
|
+
`)),process.stdout.write(w(` [4/4] Langfuse Register trace capture hooks
|
|
172
174
|
`)),process.stdout.write(`
|
|
173
|
-
`);let n=
|
|
174
|
-
`)),1;let o=
|
|
175
|
-
`),130;throw a}if(!i)gt("Keeping existing proxy configuration.");else {let a=await mt(t);if(a!==0)return a;try{
|
|
176
|
-
`+
|
|
177
|
-
`),
|
|
178
|
-
`)
|
|
179
|
-
`)
|
|
180
|
-
`)
|
|
181
|
-
`)
|
|
182
|
-
`);}function
|
|
183
|
-
`)
|
|
184
|
-
`);
|
|
185
|
-
`);}
|
|
186
|
-
`);}
|
|
187
|
-
`),
|
|
188
|
-
`);let
|
|
189
|
-
`)
|
|
190
|
-
`)
|
|
191
|
-
`);let
|
|
192
|
-
`),
|
|
193
|
-
|
|
194
|
-
`)
|
|
195
|
-
`);
|
|
196
|
-
`),
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
`
|
|
200
|
-
`)
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
`)),v=l?.inputTokens??0,_=l?.outputTokens??0,re=i.map((E,st)=>`${st+1}. ${E.tool}${E.brief?` \u2192 ${E.brief}`:""}${E.error?" [ERROR]":""} (${E.durationMs}ms)`),Mt=!!(n.slashSkill||i.some(E=>E.tool==="Skill")),ne=i.some(E=>E.tool==="Agent");if(!Mt&&!ne){u("Stop",`sid=${e}`,"skipping trace \u2014 no Skill or Agent calls found"),wt("TRACE_SKIPPED",{reason:"no_skill_or_agent"}),gr(e),j(t);return}let se=Mt?"skill":"agent",oe=Math.round(Number(BigInt(s)-BigInt(n.startNs))/1e6),ie=ss(n.model,v,_),Tt=$n(n);Tt==="prerequisite_required"&&l?.text&&(Tt="complete"),Tt==="prerequisite_required"&&(a.push({traceId:n.traceId,spanId:ht(),parentSpanId:n.spanId,name:"prerequisite-check",kind:3,startTimeUnixNano:n.startNs,endTimeUnixNano:s,attributes:Et(d(S.OBS_NAME,"prerequisite-check"),d(S.OBS_TYPE,"EVENT"),d(S.OBS_LEVEL,"WARNING"),d(S.OBS_OUTPUT,T),d("skill.name",n.slashSkill||void 0),d("execution_status","prerequisite_required")),status:{code:1}}),u("Stop",`sid=${e}`,"prerequisite-check span injected",`skill=${n.slashSkill}`));let Bt=(()=>{if(!(!Mt||!n.prompt)){if(n.slashSkill){let E=n.prompt.replace(new RegExp(`^\\/${n.slashSkill}\\s*`,"i"),"").trim();return E?J(rt(E),W.USER_INSTRUCTION):void 0}return J(rt(n.prompt),W.USER_INSTRUCTION)||void 0}})(),ae=JSON.stringify({trace_type:se,...Tt!==null&&{execution_status:Tt},...n.slashSkill?{skill_name:n.slashSkill}:{},...n.skillArtifacts?.length&&{skill_artifacts:n.skillArtifacts},...Bt!==void 0&&{user_instruction:Bt},latency_ms:oe,...v&&{tokens_input:v},..._&&{tokens_output:_},cost_usd:ie,...n.model?{model:n.model}:{},toolCount:y,errorCount:w,stopReason:r,sessionId:n.sessionId,tools:re.length?re:void 0}),nt=rt(J(n.prompt,W.TRACE_INPUT)),ls=Et(d(S.TRACE_NAME,n.traceName),d(S.TRACE_INPUT,nt),d(S.TRACE_OUTPUT,T),d(S.OBS_INPUT,nt),d(S.OBS_OUTPUT,T),d(S.TRACE_METADATA,ae),d(S.SESSION_ID,n.sessionId),d(S.USER_ID,o.user),d(S.OBS_TYPE,"GENERATION"),d(S.MODEL,n.model),v?d(S.INPUT_TOKENS,v):null,_?d(S.OUTPUT_TOKENS,_):null,d("claude.stop_reason",r),d("claude.tool_count",String(y)),d("claude.error_count",String(w)),d("claude.session_id",n.sessionId),d("flow.trace_type",se),{key:S.TRACE_TAGS,value:{arrayValue:{values:[{stringValue:se}]}}}),us={traceId:n.traceId,spanId:n.spanId,name:n.traceName,kind:1,startTimeUnixNano:n.startNs,endTimeUnixNano:s,attributes:ls,status:{code:w>0?2:1}},ds=Et(d("service.name",process.env.LANGFUSE_PROJECT_NAME||"claude-code"),d("deployment.environment",process.env.LANGFUSE_ENVIRONMENT||"default")),kr=[...a,us];u("Stop",`sid=${e}`,`totalTools=${y}`,`errorTools=${w}`,`spans=${kr.length}`,`inputTokens=${v}`,`outputTokens=${_}`,`traceOutput="${ve(T,80)}"`);let ps=await Zn(Mn(ds,kr));u("Stop",`POST status=${ps}`,`traceId=${n.traceId}`),wt("TRACE_SENT",{latencyMs:oe,totalTools:y,errorTools:w,inputTokens:v,outputTokens:_,costUsd:ie}),gr(e),j(t);}var as=m(()=>{"use strict";Zt();Qt();yr();$();os();wr();$t();H();Re();_r();A();be();});async function ci(){let t=process.argv[2];if(t==="UserPromptSubmit"){let r=await pr(),n;try{n=await q();}catch{process.stdout.write(JSON.stringify(r));return}n.authError?await Er(r,true):n.length>0?await Er(r):process.stdout.write(JSON.stringify(r));return}if(!await tn()){let r=[];process.stdin.on("data",n=>r.push(n)),process.stdin.on("end",()=>process.stdout.write(r.join("")));return}let e=await pr();switch(t){case "PreToolUse":await xn(e);break;case "PostToolUse":await es(e);break;case "Stop":await is(e);break;default:process.stderr.write(`[flow-obs] unknown event: ${t}
|
|
205
|
-
`),process.stdout.write(JSON.stringify(e));}}var cs=m(()=>{"use strict";$();$t();Fn();Dn();rs();as();ci().catch(t=>{process.stderr.write(`[flow-obs] fatal: ${t.message}
|
|
206
|
-
`),process.exit(0);});});var ui=new Set(["UserPromptSubmit","PreToolUse","PostToolUse","Stop"]),[,,M,ee]=process.argv;function St(t,e){let r=t.indexOf(e);return r!==-1?t[r+1]:void 0}if(M==="--version"||M==="-v"){let{version:t}=ce();process.stdout.write(t+`
|
|
207
|
-
`),process.exit(0);}else if(M==="--help"||M==="-h"){let{bold:t,cyan:e,dim:r}=(ot(),b(Ne)),{version:n}=ce();process.stdout.write(`
|
|
175
|
+
`);let n=mo();if(_e(1,r,"Checking Claude Code..."),Te()){let s=rr();K(s?`Already installed (${s}) \u2014 skipping.`:"Already installed \u2014 skipping.");}else {gt("Not found. Installing via npm...");let s=nn();if(!s.success)return zt(s.message??"Failed to install Claude Code."),process.stderr.write(R(` Setup aborted at step 1. Resolve the error above and try again.
|
|
176
|
+
`)),1;let o=rr();K(o?`Claude Code ${o} installed.`:"Claude Code installed.");}if(_e(2,r,"Configuring proxy..."),go(n)){let s=n.env.ANTHROPIC_BASE_URL;fn(`Proxy already configured (${s})`);let o=t.nonInteractive||!process.stdin.isTTY,i=false;if(!o)try{i=await wo(I(" ? ")+"Replace existing proxy configuration? [y/N]: ");}catch(a){if(a.message==="SIGINT")return process.stdout.write(`
|
|
177
|
+
`),130;throw a}if(!i)gt("Keeping existing proxy configuration.");else {let a=await mt(t);if(a!==0)return a;try{H(Mt()),K("Proxy reconfigured.");}catch(c){return zt(`Could not write proxy config: ${c.message}`),1}}}else {let s=await mt(t);if(s!==0)return s;try{H(Mt()),K("Proxy configured."),gt(`Settings: ${A()}`);}catch(o){return zt(`Could not write proxy config: ${o.message}`),1}}if(_e(3,r,"Configuring AI Usage..."),t.url){let{runInit:s}=await Promise.resolve().then(()=>(lr(),cr)),o=await s({noInteractive:true,url:t.url,skipHint:true});if(o!==0)return o;K("AI Usage configured with custom URL.");}else if(ho(n))K("Already configured \u2014 skipping.");else try{H(V),K("AI Usage configured."),gt(`Settings: ${A()}`);}catch(s){return zt(`Could not write AI Usage config: ${s.message}`),1}if(_e(4,r,"Configuring Langfuse..."),Eo(n))K("Already configured \u2014 skipping.");else {let s,o;try{({settingsPath:s,preserved:o}=en());}catch(i){return zt(`Could not write hooks: ${i.message}`),1}K("Hooks registered (UserPromptSubmit, PreToolUse, PostToolUse, Stop)"),o.length>0&&(fn(`Third-party hooks preserved on: ${o.join(", ")}`),gt("flow-ai-obs was prepended \u2014 it executes first.")),gt(`Settings: ${s}`),gt(`Backup: ${s}.bkp`);}return process.stdout.write(`
|
|
178
|
+
`+L(" \u2713 Setup complete. Run `claude` to start.\n\n")),0}var hn=m(()=>{"use strict";k();it();Ht();Xt();qt();nr();});var En={};W(En,{runOtelHeaders:()=>To});async function To(){let t={},e=ft();return e&&(t["x-flow-user"]=e),process.stdout.write(JSON.stringify(t)+`
|
|
179
|
+
`),0}var wn=m(()=>{"use strict";N();});var Tn={};W(Tn,{runCheck:()=>yo});function ur(t){return !t||t.length<=8?"****":t.slice(0,4)+"****...****"+t.slice(-4)}function Zt(t){process.stdout.write(` \u2713 ${t}
|
|
180
|
+
`);}function Oe(t){process.stdout.write(` \u26A0 ${t}
|
|
181
|
+
`);}function ke(t){process.stdout.write(` \u2717 ${t}
|
|
182
|
+
`);}function U(t){process.stdout.write(` ${t}
|
|
183
|
+
`);}function $(){process.stdout.write(`
|
|
184
|
+
`);}async function yo(){$(),process.stdout.write(` flow-claude-observability \u2014 configuration check
|
|
185
|
+
`),$(),process.stdout.write(` Auth
|
|
186
|
+
`);let t=()=>Pt(p.ANTHROPIC_AUTH_TOKEN)??process.env[p.ANTHROPIC_AUTH_TOKEN],e=B(t());if(!e){Oe("Not authenticated \u2014 starting setup..."),$();let a=await mt();if(a!==0)return a;if(e=B(t()),!e)return ke("Authentication failed"),$(),1;$(),process.stdout.write(` Auth
|
|
187
|
+
`);}if(!await he()){Oe("Session expired \u2014 re-authenticating..."),$();let a=await mt();if(a!==0)return a;$(),process.stdout.write(` Auth
|
|
188
|
+
`);}let r=await Jt()||e.clientId;Zt("Authenticated"),U(`Tenant: ${e.tenant}`),U(`User: ${r}`),$(),process.stdout.write(` Native OTEL
|
|
189
|
+
`);let n={};try{let a=g__namespace.readFileSync(A(),"utf8");n=JSON.parse(a).env||{};}catch{}let s=Object.keys(V).filter(a=>!n[a]);if(s.length===0?(Zt("All OTEL env vars present in settings.json"),U(`Endpoint: ${n.OTEL_EXPORTER_OTLP_ENDPOINT}`)):(Oe(`${s.length} OTEL var(s) missing from settings.json \u2014 native metrics/logs disabled`),s.forEach(a=>ke(`Missing: ${a}`)),U("Run: flow-ai-obs init (restores missing vars automatically)")),$(),process.stdout.write(` Tracing
|
|
190
|
+
`),process.env[p.FLOW_TELEMETRY]==="true"){Zt("FLOW_TELEMETRY=true (direct mode enabled)");let a=[p.LANGFUSE_BASE_URL,p.LANGFUSE_PUBLIC_KEY,p.LANGFUSE_SECRET_KEY].filter(c=>!process.env[c]);a.length>0&&a.forEach(c=>Oe(`Missing: ${c}`));}else U("FLOW_TELEMETRY not set \u2014 direct mode inactive (gateway mode may still be active)");let i=await J();if(!i||i.length===0)return i&&i.authError?ke("Token refresh failed \u2014 gateway mode could not activate"):(ke("No active destinations \u2014 no traces will be sent"),U("For direct mode: set FLOW_TELEMETRY=true + LANGFUSE_BASE_URL + LANGFUSE_PUBLIC_KEY + LANGFUSE_SECRET_KEY"),U("For gateway mode: run flow-claude-observability auth login")),$(),1;for(let a of i)if(a.mode==="gateway"){let c=await It();Zt("Mode: gateway"),U(`Endpoint: ${a.endpoint}`),U(`Token: ${ur(c?.accessToken)}`);}else a.mode==="direct"&&(Zt("Mode: direct"),U(`Endpoint: ${a.endpoint}`),U(`PK: ${ur(process.env[p.LANGFUSE_PUBLIC_KEY])}`),U(`SK: ${ur(process.env[p.LANGFUSE_SECRET_KEY])}`));return $(),process.stdout.write(` All checks passed \u2014 observability is active.
|
|
191
|
+
`),$(),0}var yn=m(()=>{"use strict";Ee();N();qt();k();Xt();});function G(t,e){let r=typeof t=="object"?JSON.stringify(t):String(t??"");return r.length>e?r.slice(0,e)+" \u2026[truncated]":r}function ve(t,e=100){return String(t??"").split(`
|
|
192
|
+
`)[0].slice(0,e).trim()}function dr(){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 j(t){process.stdout.write(JSON.stringify(t));}var Ct=m(()=>{"use strict";});function Q(){return String(BigInt(Date.now())*1000000n)}var pr,ht,Qt=m(()=>{"use strict";pr=()=>crypto.randomBytes(16).toString("hex"),ht=()=>crypto.randomBytes(8).toString("hex");});function Co(t,e){let r=Rt.resolve(t);if(!r.startsWith(e))throw new Error(`Path traversal detected: ${t}`);return r}function fr(t){if(!Po.test(t))throw new Error(`Invalid session ID: ${t}`);return Co(Rt.join(dt.tmpdir(),`flow-obs-${t}.json`),bo)}function Nt(t){let e=fr(t);if(!g.existsSync(e))return null;try{return JSON.parse(g.readFileSync(e,"utf8"))}catch{return null}}function Ut(t,e){g.writeFileSync(fr(t),JSON.stringify(e),{encoding:"utf8",mode:384});}function mr(t){try{g.unlinkSync(fr(t));}catch{}}var Po,bo,te=m(()=>{"use strict";Po=/^[0-9a-f-]{1,64}$/i,bo=Rt.normalize(dt.tmpdir())+Rt.sep;});function An(t){if(!t||!g.existsSync(t))return null;try{let e=g.readFileSync(t,"utf8").trimEnd().split(`
|
|
193
|
+
`);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 gr(t){if(!t||!g.existsSync(t))return null;try{let e=g.readFileSync(t,"utf8").trimEnd().split(`
|
|
194
|
+
`),r=[],n=0,s=0;for(let o=e.length-1;o>=0;o--)try{let i=JSON.parse(e[o]);if(i.type==="user")break;if(i.type==="assistant"){let c=(i.message?.content??[]).filter(d=>d.type==="text").map(d=>d.text??"").join("");c&&r.unshift(c);let u=i.message?.usage??{};n+=(u.input_tokens??0)+(u.cache_read_input_tokens??0)+(u.cache_creation_input_tokens??0),s+=u.output_tokens??0;}}catch{}return !r.length&&n===0?null:{text:r.join(`
|
|
195
|
+
|
|
196
|
+
`),inputTokens:n,outputTokens:s}}catch{}return null}var hr=m(()=>{"use strict";});function In(t){return t.replace(":","/")}function Ae(t,e){if(!t)return null;let r=In(t),n=[Rt.join(dt.homedir(),".claude","skills",r,"SKILL.md"),Rt.join(e??"",".claude","skills",r,"SKILL.md")];for(let s of n)if(g.existsSync(s))try{return g.readFileSync(s,"utf8")}catch{}return null}function Pn(t){return t.split(`
|
|
197
|
+
`)[0].match(/^\/([a-z][a-z0-9-]*(?::[a-z][a-z0-9-]*)?)(?:\s.*)?$/i)?.[1]??null}function bn(t){return !!t.slashSkill||t.toolCalls.some(n=>n.tool==="Skill")?t.toolCalls.some(n=>n.tool==="Skill"&&!n.synthetic||Mo.has(n.tool))?"complete":"prerequisite_required":null}function Le(t,e){if(!t)return null;let r=In(t),n=[Rt.join(dt.homedir(),".claude","skills",r),Rt.join(e??"",".claude","skills",r)],s=null;for(let a of n)if(g.existsSync(Rt.join(a,"SKILL.md"))){s=a;break}if(!s)return null;let o=[];function i(a,c){for(let u of g.readdirSync(a,{withFileTypes:true})){if(Fo.has(u.name)||Do.has(u.name)||xo.has(Rt.extname(u.name)))continue;let d=c?`${c}/${u.name}`:u.name;u.isDirectory()?i(Rt.join(a,u.name),d):o.push(d);}}return i(s,""),o.length>0?o:null}var Fo,xo,Do,Mo,Re=m(()=>{"use strict";Fo=new Set([".venv","__pycache__",".git","node_modules"]),xo=new Set([".pyc",".pyo"]),Do=new Set(["SKILL.md",".DS_Store",".gitignore"]);Mo=new Set(["Read","Write","Edit","MultiEdit","Bash","Glob","Grep","TodoWrite","WebFetch","WebSearch","Agent","Task"]);});function jo(t){try{let e=t.split(".")[1].replace(/-/g,"+").replace(/_/g,"/");return JSON.parse(Buffer.from(e,"base64").toString())}catch{return null}}function Wo(t,e,r,n){return new Promise(s=>{let o=new URL(t),i=o.protocol==="https:",a=(i?hs__default.default:Cs__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,"")}},c=>{c.resume(),s(c.statusCode??0);});a.on("error",()=>s(0)),a.setTimeout(5e3,()=>{a.destroy(),s(0);}),a.write(e),a.end();})}async function Et(t,e={}){try{let r=B(process.env[p.ANTHROPIC_AUTH_TOKEN]);if(!r)return;let n,s=new Promise((h,E)=>{n=setTimeout(()=>E(new Error("getToken timeout")),4e3),n.unref();}),{accessToken:o}=await Promise.race([q(r),s]);clearTimeout(n);let i=jo(o);if(!i)return;let a=i.tenant||r.tenant,c=JSON.stringify({action:t,booster:Ve().BOOSTER,metadata:e,success:!0,tenant:a,timestamp:new Date().toISOString(),os:process.platform,user:{email:i.email||"",id:i.sub||"",name:i.name||i.email||""}}),u=pt(Ve().API_URL),d=await Wo(u,c,o,a);l("metrics.logEvent",`action=${t} status=${d}`);}catch(r){l("metrics.logEvent",`silenced error: ${r.message}`);}}var Ie=m(()=>{"use strict";k();Bt();N();M();});async function Er(t,e=false){if(e){process.stdout.write(JSON.stringify({decision:"block",reason:Vo})+`
|
|
198
|
+
`);return}let n=!!(await J()).authError,s=t.session_id||"unknown",o=t.prompt||"",i=t.cwd||"",a=An(t.transcript_path)||pr(),c=Pn(o),u=c?Ae(c,i):null,d=c?Le(c,i):null;Ut(s,{traceId:pr(),spanId:ht(),startNs:Q(),sessionId:s,prompt:o,cwd:i,traceName:a,transcriptPath:t.transcript_path||"",model:process.env[p.ANTHROPIC_MODEL]||"",toolCalls:[],spans:[],pendingTool:null,slashSkill:c,skillContent:u,skillArtifacts:d}),Et("SESSION_STARTED",{traceType:c?"skill":"prompt",slashSkill:c,clientIdExpired:n}),l("UserPromptSubmit",`sid=${s}`,`traceName=${a}`,`slashSkill=${c}`),j(t);}var Vo,Cn=m(()=>{"use strict";Qt();te();hr();Re();Ct();M();k();N();Ie();Vo=`\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 ${ct()}/settings/api-keys to generate a new API key, then run: flow-ai-obs auth login`;});async function Nn(t){let e=t.session_id||"unknown",r=t.tool_name||"unknown",n=t.tool_input||{},s=Nt(e);s&&(s.pendingTool={name:r,inputStr:G(n,Y.TOOL_INPUT),startNs:Q()},Ut(e,s)),l("PreToolUse",`sid=${e}`,`tool=${r}`,`stateFound=${!!s}`),j(t);}var Un=m(()=>{"use strict";Qt();te();Ct();M();k();});function f(t,e){return e==null||e===""?null:{key:t,value:{stringValue:String(e)}}}function wt(...t){return t.filter(e=>e!==null)}function $n(t,e){return {resourceSpans:[{resource:{attributes:t},scopeSpans:[{scope:Yo,spans:Array.isArray(e)?e:[e]}]}]}}var Yo,y,Fn=m(()=>{"use strict";k();Yo={name:je.SCOPE_NAME,version:je.SCOPE_VERSION},y={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 Dn(t,e,r,n,s){if(process.env[p.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{g.writeFileSync(xn,o+`
|
|
199
|
+
`,{flag:"a",encoding:"utf8",mode:384}),l("sendTraces:dump",`request appendada em ${xn}`);}catch(i){l("sendTraces:dump",`falha ao salvar: ${i.message}`);}}function zo(t){let e=new URL(t),r=new URL(At().GATEWAY_HEALTH);return r.hostname=e.hostname,r.port=e.port,r.protocol=e.protocol,r}function Mn(t,e){return new Promise((r,n)=>{let s=t._isSSL?hs__default.default:Cs__default.default;t.headers=Object.assign({},t.headers,{Connection:"close"});let o=s.request(t,i=>{let a=[];i.on("data",c=>a.push(c)),i.on("end",()=>r({statusCode:i.statusCode??0,body:a.join("")}));});o.setTimeout(1e4,()=>{o.destroy(new Error("Request timeout"));}),o.on("error",i=>n(new Error(`Network error: ${i.message}`))),e&&o.write(e),o.end();})}async function Bn(t){let e;try{e=zo(t);}catch{return false}let r=e.protocol==="https:";try{let n=await Mn({hostname:e.hostname,port:e.port||(r?443:80),path:e.pathname,method:"GET",_isSSL:r},null);return l("checkHealth",`url=${e.href} status=${n.statusCode}`),n.statusCode>=200&&n.statusCode<300}catch{return false}}async function Pe(t,e){let r=JSON.stringify(t),n=new URL(e),s=n.protocol==="https:",o={"Content-Type":"application/json","Content-Length":Buffer.byteLength(r),"x-flow-user":ft()??"","x-flow-api-key":"Basic czNjcjN0LXA0c3N3MHJk"};l("sendTraces:request",`POST ${e}`),l("sendTraces:request",`headers=${JSON.stringify(o)}`),l("sendTraces:request",`body=${r.slice(0,500)}${r.length>500?"\u2026":""}`);try{let i=await Mn({hostname:n.hostname,port:n.port||(s?443:80),path:n.pathname,method:"POST",headers:o,_isSSL:s},r);return l("sendTraces:response",`status=${i.statusCode}`),Dn(e,o,r,i.statusCode,i.body),i.statusCode}catch(i){return l("sendTraces:error",i.message),Dn(e,o,r,0,i.message),0}}var xn,Hn=m(()=>{"use strict";k();M();N();xn=Rt.join(dt.tmpdir(),"flow-obs-requests.ndjson");});function Zo(){let t=parseInt(process.env[p.BUFFER_TTL_DAYS]??"",10);return (Number.isFinite(t)?Math.max(D.MIN_TTL_DAYS,Math.min(D.MAX_TTL_DAYS,t)):D.DEFAULT_TTL_DAYS)*24*60*60*1e3}function Qo(){let t=parseInt(process.env[p.BUFFER_MAX_FILES]??"",10);return Number.isFinite(t)?Math.max(D.MIN_MAX_FILES,Math.min(D.MAX_MAX_FILES,t)):D.DEFAULT_MAX_FILES}function Wn(t){if(/[/\\]/.test(t))throw new Error(`Invalid buffer fileId: ${t}`);return Rt__namespace.default.join(dt__namespace.default.tmpdir(),`${D.FILE_PREFIX}${t}.json`)}function Sr(){let t=dt__namespace.default.tmpdir(),e;try{e=g__namespace.default.readdirSync(t);}catch{return []}return e.filter(r=>r.startsWith(D.FILE_PREFIX)&&r.endsWith(".json")).map(r=>{let n=Rt__namespace.default.join(t,r),s=0;try{s=g__namespace.default.statSync(n).mtimeMs;}catch{}return {full:n,mtime:s}}).sort((r,n)=>r.mtime-n.mtime).map(r=>r.full)}function ee(t){try{let e=Qo(),r=Sr();if(r.length>=e){let o=r.slice(0,r.length-e+1);for(let i of o)try{g__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 g__namespace.default.writeFileSync(Wn(n),JSON.stringify(s),{encoding:"utf8",mode:384}),l("buffer",`saved fileId=${n}`),n}catch(e){return l("buffer",`saveToBuffer failed: ${e.message}`),null}}function Vn(t){let e=Sr(),r=t!=null&&t>0?t:e.length,n=[];for(let s of e){if(n.length>=r)break;try{let o=g__namespace.default.readFileSync(s,"utf8"),i=JSON.parse(o);i&&i.fileId&&i.payload&&n.push(i);}catch{l("buffer",`skipping malformed file: ${s}`);}}return n}function Yn(t){try{g__namespace.default.unlinkSync(Wn(t)),l("buffer",`deleted fileId=${t}`);}catch{}}function Gn(){let t=Date.now()-Zo();for(let e of Sr())try{let{mtimeMs:r}=g__namespace.default.statSync(e);r<t&&(g__namespace.default.unlinkSync(e),l("buffer",`evicted stale: ${Rt__namespace.default.basename(e)}`));}catch{}}var Jn=m(()=>{"use strict";k();M();});async function ti(t){Gn();let e=Vn(D.REPLAY_BATCH_SIZE);e.length&&(l("replayBufferedTraces",`replaying ${e.length} buffered trace(s)`),await Promise.allSettled(e.map(async r=>{try{let n=await Pe(r.payload,t.endpoint);n>=200&&n<300?(Yn(r.fileId),l("replayBufferedTraces",`replayed fileId=${r.fileId} status=${n}`)):l("replayBufferedTraces",`replay failed fileId=${r.fileId} status=${n}`);}catch(n){l("replayBufferedTraces",`replay error fileId=${r.fileId}: ${n.message}`);}})));}async function Kn(t){let e=await J();if(!e.length)return e.authError&&(l("postToLangfuse","auth refresh failed \u2014 buffering trace"),ee(t)),0;let r=await Promise.all(e.map(async o=>{if(o.mode!=="gateway")return {creds:o,healthy:true};let i=await Bn(o.endpoint);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 ti(n),(await Promise.all(r.map(async({creds:o,healthy:i})=>{if(o.mode==="gateway"){if(!i)return l("postToLangfuse","gateway health check failed \u2014 buffering trace"),ee(t),0;let c=await Pe(t,o.endpoint);return (c===0||c>=500)&&(l("postToLangfuse",`gateway send failed (status ${c}) \u2014 buffering trace`),ee(t)),c}let a=await Pe(t,o.endpoint);return (a===0||a>=500)&&(l("postToLangfuse",`direct endpoint unavailable (status ${a}) \u2014 buffering trace`),ee(t)),a}))).find(o=>o!==0)??0}var qn=m(()=>{"use strict";N();M();Hn();Jn();k();});var Tr=m(()=>{"use strict";Fn();qn();});function et(t){if(t==null)return "";let e=typeof t=="string"?t:JSON.stringify(t);return si.reduce((r,{re:n,replace:s})=>r.replace(n,s),e)}var F,ei,ri,ni,Xn,si,yr=m(()=>{"use strict";F="[REDACTED]",ei="[REDACTED-EMAIL]",ri="[REDACTED-CPF]",ni="[REDACTED-CNPJ]",Xn="[REDACTED-PHONE]",si=[{re:/\b(sk-[A-Za-z0-9_\-]{20,})/g,replace:()=>`sk-${F}`},{re:/\b(pk-[A-Za-z0-9_\-]{20,})/g,replace:()=>`pk-${F}`},{re:/\b(Bearer\s+)[A-Za-z0-9\-._~+/]+=*/gi,replace:(t,e)=>`${e}${F}`},{re:/\b(Basic\s+)[A-Za-z0-9+/]+=*/gi,replace:(t,e)=>`${e}${F}`},{re:/(-----BEGIN [A-Z ]+-----)[^-]*(-----END [A-Z ]+-----)/g,replace:(t,e,r)=>`${e}
|
|
200
|
+
${F}
|
|
201
|
+
${r}`},{re:/\b(AKIA[0-9A-Z]{16})\b/g,replace:()=>`AKIA${F}`},{re:/(aws_secret_access_key\s*[=:]\s*)([A-Za-z0-9/+]{40})/gi,replace:(t,e)=>`${e}${F}`},{re:/\b(ghp_[A-Za-z0-9]{36,})/g,replace:()=>`ghp_${F}`},{re:/\b(github_pat_[A-Za-z0-9_]{36,})/gi,replace:()=>`github_pat_${F}`},{re:/\b(eyJ[A-Za-z0-9_\-]+\.eyJ[A-Za-z0-9_\-]+\.[A-Za-z0-9_\-]+)/g,replace:()=>`eyJ.${F}`},{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}${F}${r}`},{re:/([a-z][a-z0-9+\-.]*:\/\/[^:/?#\s]*):([^@\s]+)@/gi,replace:(t,e)=>`${e}:${F}@`},{re:/[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}/g,replace:()=>ei},{re:/\b\d{3}\.\d{3}\.\d{3}-\d{2}\b/g,replace:()=>ri},{re:/\b\d{2}\.\d{3}\.\d{3}\/\d{4}-\d{2}\b/g,replace:()=>ni},{re:/\(\d{2}\)\s?\d{4,5}[-\s]?\d{4}/g,replace:()=>Xn},{re:/\+55[\s-]?\d{2}[\s-]?\d{4,5}[-\s]?\d{4}/g,replace:()=>Xn}];});async function zn(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=Nt(e);if(!i){j(t);return}let a=Q(),c=i.pendingTool,u=c?.name===r,d=u?c.startNs:String(BigInt(a)-200000000n),h=u?c.inputStr:G(n,Y.TOOL_INPUT),E=h,S=null;if(r==="Skill"){let ie=typeof n=="object"&&n!==null?n.skill||n.name||n.skillName||n.commandName||String(Object.values(n)[0]??""):String(n);S=ie?String(ie).trim():null;let st=S?Ae(S,i.cwd):null;st&&(E=st,i.skillContent||(i.skillContent=st),i.skillArtifacts||(i.skillArtifacts=Le(S,i.cwd))),S&&!i.slashSkill&&(i.slashSkill=S),l("PostToolUse","Skill tool detected",`skillName=${S}`,`contentFound=${!!st}`);}let v=et(G(o,Y.TOOL_OUTPUT)),O=/\b(error|exception|failed|failure|traceback|errno)\b/i.test(v.slice(0,500)),St=O?"ERROR":"DEFAULT",nt=ht(),Tt=Math.round(Number(BigInt(a)-BigInt(d))/1e6),se={Agent:"AGENT",Task:"AGENT"}[r]??"TOOL",oe=r==="Skill"&&S?S:ve(h,60);i.toolCalls.push({tool:r,brief:oe,error:O,durationMs:Tt});let Ft=i.spans;Ft.push({traceId:i.traceId,spanId:nt,parentSpanId:i.spanId,name:r,kind:3,startTimeUnixNano:d,endTimeUnixNano:a,attributes:wt(f(y.OBS_NAME,r),f(y.OBS_TYPE,se),f(y.OBS_LEVEL,St),f(y.OBS_INPUT,et(E)),f(y.OBS_OUTPUT,v),f("tool.name",r),f("tool.error",String(O)),r==="Skill"&&S?f("skill.name",S):null,r==="Skill"?f("skill.invocation","slash-command"):null),status:{code:O?2:1}}),i.pendingTool=null,Ut(e,i),O&&Et("TOOL_ERROR",{toolName:r}),l("PostToolUse",`sid=${e}`,`tool=${r}`,`error=${O}`,`durationMs=${Tt}`,`totalSpans=${Ft.length}`),j(t);}var Zn=m(()=>{"use strict";Qt();te();Tr();Ct();Re();M();k();yr();Ie();});function ts(t,e,r){let n=Object.keys(Qn).find(i=>(t??"").toLowerCase().includes(i));if(!n)return;let s=Qn[n],o=(e*s.input+r*s.output)/1e6;return Math.round(o*1e6)/1e6}var Qn,es=m(()=>{"use strict";Qn={"claude-opus-4-6":{input:15,output:75},"claude-opus-4-5":{input:15,output:75},"claude-sonnet-4-6":{input:3,output:15},"claude-sonnet-4-5":{input:3,output:15},"claude-haiku-4-5":{input:.8,output:4},"claude-4-6-opus":{input:15,output:75},"claude-4-6-sonnet":{input:3,output:15},"claude-4-5-opus":{input:15,output:75},"claude-4-5-sonnet":{input:3,output:15},"claude-4-5-haiku":{input:.8,output:4},"claude-3-5-sonnet-20241022":{input:3,output:15},"claude-3-5-haiku-20241022":{input:.8,output:4},"claude-3-opus-20240229":{input:15,output:75}};});async function rs(t){let e=t.session_id||"unknown",r=t.stop_reason||"end_turn",n=Nt(e);if(!n){j(t);return}n.slashSkill&&!/^[a-z][a-z0-9-]*(?::[a-z][a-z0-9-]*)?$/i.test(n.slashSkill)&&(l("Stop",`sid=${e}`,`slashSkill rejected post-disk: "${n.slashSkill}"`),n.slashSkill=null);let s=Q(),o=await zr(),i=n.toolCalls,a=n.spans;if(n.slashSkill&&!i.some(T=>T.tool==="Skill")){let T=ht(),ot=n.skillContent?n.skillContent:JSON.stringify({skill:n.slashSkill});i.push({tool:"Skill",brief:n.slashSkill,error:false,durationMs:0,synthetic:true}),a.push({traceId:n.traceId,spanId:T,parentSpanId:n.spanId,name:"Skill",kind:3,startTimeUnixNano:n.startNs,endTimeUnixNano:n.startNs,attributes:wt(f(y.OBS_NAME,"Skill"),f(y.OBS_TYPE,"TOOL"),f(y.OBS_LEVEL,"DEFAULT"),f(y.OBS_INPUT,ot),f(y.OBS_OUTPUT,"loaded via slash command"),f("tool.name","Skill"),f("tool.error","false"),f("skill.name",n.slashSkill),f("skill.invocation","slash-command")),status:{code:1}}),l("Stop",`slashSkill=${n.slashSkill}`,"synthetic span injected");}let c=t.transcript_path||n.transcriptPath||"",u=gr(c);if(c&&(i.some(T=>T.tool==="Skill"&&!T.synthetic)||!!n.slashSkill)&&!u?.text){await new Promise(ot=>setTimeout(ot,500));let T=gr(c);T?.text&&(u=T);}l("Stop",`transcriptPath=${c||"(empty)"}`,`assistantOut=${u?`text=${u.text.length}chars`:"null"}`);let h=i.length,E=i.filter(T=>T.error).length,S=et(u?.text?G(u.text,Y.TRACE_OUTPUT):h===0?"No tools used":i.map((T,ot)=>`${ot+1}. ${T.tool}${T.brief?` \u2192 ${T.brief}`:""}${T.error?" [ERROR]":""}`).join(`
|
|
202
|
+
`)),v=u?.inputTokens??0,O=u?.outputTokens??0,St=i.map((T,ot)=>`${ot+1}. ${T.tool}${T.brief?` \u2192 ${T.brief}`:""}${T.error?" [ERROR]":""} (${T.durationMs}ms)`),nt=!!(n.slashSkill||i.some(T=>T.tool==="Skill")),Tt=i.some(T=>T.tool==="Agent");if(!nt&&!Tt){l("Stop",`sid=${e}`,"skipping trace \u2014 no Skill or Agent calls found"),Et("TRACE_SKIPPED",{reason:"no_skill_or_agent"}),mr(e),j(t);return}let ne=nt?"skill":"agent",se=Math.round(Number(BigInt(s)-BigInt(n.startNs))/1e6),oe=ts(n.model,v,O),yt=bn(n);yt==="prerequisite_required"&&u?.text&&(yt="complete"),yt==="prerequisite_required"&&(a.push({traceId:n.traceId,spanId:ht(),parentSpanId:n.spanId,name:"prerequisite-check",kind:3,startTimeUnixNano:n.startNs,endTimeUnixNano:s,attributes:wt(f(y.OBS_NAME,"prerequisite-check"),f(y.OBS_TYPE,"EVENT"),f(y.OBS_LEVEL,"WARNING"),f(y.OBS_OUTPUT,S),f("skill.name",n.slashSkill||void 0),f("execution_status","prerequisite_required")),status:{code:1}}),l("Stop",`sid=${e}`,"prerequisite-check span injected",`skill=${n.slashSkill}`));let Ft=(()=>{if(!(!nt||!n.prompt)){if(n.slashSkill){let T=n.prompt.replace(new RegExp(`^\\/${n.slashSkill}\\s*`,"i"),"").trim();return T?G(et(T),Y.USER_INSTRUCTION):void 0}return G(et(n.prompt),Y.USER_INSTRUCTION)||void 0}})(),ie=JSON.stringify({trace_type:ne,...yt!==null&&{execution_status:yt},...n.slashSkill?{skill_name:n.slashSkill}:{},...n.skillArtifacts?.length&&{skill_artifacts:n.skillArtifacts},...Ft!==void 0&&{user_instruction:Ft},latency_ms:se,...v&&{tokens_input:v},...O&&{tokens_output:O},cost_usd:oe,...n.model?{model:n.model}:{},toolCount:h,errorCount:E,stopReason:r,sessionId:n.sessionId,tools:St.length?St:void 0}),st=et(G(n.prompt,Y.TRACE_INPUT)),os=wt(f(y.TRACE_NAME,n.traceName),f(y.TRACE_INPUT,st),f(y.TRACE_OUTPUT,S),f(y.OBS_INPUT,st),f(y.OBS_OUTPUT,S),f(y.TRACE_METADATA,ie),f(y.SESSION_ID,n.sessionId),f(y.USER_ID,o.user),f(y.OBS_TYPE,"GENERATION"),f(y.MODEL,n.model),v?f(y.INPUT_TOKENS,v):null,O?f(y.OUTPUT_TOKENS,O):null,f("claude.stop_reason",r),f("claude.tool_count",String(h)),f("claude.error_count",String(E)),f("claude.session_id",n.sessionId),f("flow.trace_type",ne),{key:y.TRACE_TAGS,value:{arrayValue:{values:[{stringValue:ne}]}}}),is={traceId:n.traceId,spanId:n.spanId,name:n.traceName,kind:1,startTimeUnixNano:n.startNs,endTimeUnixNano:s,attributes:os,status:{code:E>0?2:1}},as=wt(f("service.name",process.env.LANGFUSE_PROJECT_NAME||"claude-code"),f("deployment.environment",process.env.LANGFUSE_ENVIRONMENT||"default")),_r=[...a,is];l("Stop",`sid=${e}`,`totalTools=${h}`,`errorTools=${E}`,`spans=${_r.length}`,`inputTokens=${v}`,`outputTokens=${O}`,`traceOutput="${ve(S,80)}"`);let cs=await Kn($n(as,_r));l("Stop",`POST status=${cs}`,`traceId=${n.traceId}`),Et("TRACE_SENT",{latencyMs:se,totalTools:h,errorTools:E,inputTokens:v,outputTokens:O,costUsd:oe}),mr(e),j(t);}var ns=m(()=>{"use strict";Qt();te();Tr();N();es();hr();Ct();M();Re();yr();k();Ie();});async function oi(){let t=process.argv[2];if(t==="UserPromptSubmit"){let r=await dr(),n;try{n=await J();}catch{process.stdout.write(JSON.stringify(r));return}n.authError?await Er(r,true):n.length>0?await Er(r):process.stdout.write(JSON.stringify(r));return}if(!await Zr()){let r=[];process.stdin.on("data",n=>r.push(n)),process.stdin.on("end",()=>process.stdout.write(r.join("")));return}let e=await dr();switch(t){case "PreToolUse":await Nn(e);break;case "PostToolUse":await zn(e);break;case "Stop":await rs(e);break;default:process.stderr.write(`[flow-obs] unknown event: ${t}
|
|
203
|
+
`),process.stdout.write(JSON.stringify(e));}}var ss=m(()=>{"use strict";N();Ct();Cn();Un();Zn();ns();oi().catch(t=>{process.stderr.write(`[flow-obs] fatal: ${t.message}
|
|
204
|
+
`),process.exit(0);});});var ai=new Set(["UserPromptSubmit","PreToolUse","PostToolUse","Stop"]),[,,x,re]=process.argv;function rt(t,e){let r=t.indexOf(e);return r!==-1?t[r+1]:void 0}if(x==="--version"||x==="-v"){let{version:t}=ae();process.stdout.write(t+`
|
|
205
|
+
`),process.exit(0);}else if(x==="--help"||x==="-h"){let{bold:t,cyan:e,dim:r}=(it(),P(Ce)),{version:n}=ae();process.stdout.write(`
|
|
208
206
|
`+t(" flow-ai-obs")+r(" v"+n)+`
|
|
209
207
|
|
|
210
208
|
`),process.stdout.write(e(" init")+r(` Auth (if needed) + hooks + native OTEL
|
|
@@ -224,13 +222,13 @@ ${r}`},{re:/\b(AKIA[0-9A-Z]{16})\b/g,replace:()=>`AKIA${D}`},{re:/(aws_secret_ac
|
|
|
224
222
|
|
|
225
223
|
`)),process.stdout.write(r(` (Hook events: UserPromptSubmit | PreToolUse | PostToolUse | Stop)
|
|
226
224
|
|
|
227
|
-
`)),process.exit(0);}else if(
|
|
228
|
-
`),await(
|
|
229
|
-
`),process.exit(1);});else if(
|
|
230
|
-
`),process.exit(1);});else if(
|
|
225
|
+
`)),process.exit(0);}else if(x==="init"||x==="install")(async()=>{x==="install"&&process.stderr.write(`Warning: "install" is deprecated, use "init" instead
|
|
226
|
+
`),await(vt(),P(kt)).checkForUpdateInteractive();let{runInit:t}=(lr(),P(cr)),e=process.argv.slice(3);process.exit(await t({url:rt(e,"--custom-url"),noInteractive:e.includes("--no-interactive")}));})().catch(t=>{process.stderr.write(`Unexpected error: ${t.message}
|
|
227
|
+
`),process.exit(1);});else if(x==="setup")(async()=>{await(vt(),P(kt)).checkForUpdateInteractive();let{runSetup:t}=(hn(),P(gn)),e=process.argv.slice(3);process.exit(await t({clientId:rt(e,"--client-id"),clientSecret:rt(e,"--client-secret"),tenant:rt(e,"--tenant"),nonInteractive:e.includes("--non-interactive"),url:rt(e,"--custom-url")}));})().catch(t=>{process.stderr.write(`Unexpected error: ${t.message}
|
|
228
|
+
`),process.exit(1);});else if(x==="auth")(async()=>{let{runLogin:t,runLogout:e,runStatus:r}=(Xt(),P(ir)),n=0;if(re==="login"||!re){await(vt(),P(kt)).checkForUpdateInteractive();let s=process.argv.slice(4);n=await t({clientId:rt(s,"--client-id"),clientSecret:rt(s,"--client-secret"),tenant:rt(s,"--tenant")});}else if(re==="logout"){let s=process.argv.includes("--force");n=await e(s);}else re==="status"?(await(vt(),P(kt)).checkForUpdateInteractive(),n=await r()):(process.stderr.write(`Unknown auth subcommand: ${re}
|
|
231
229
|
`),process.stderr.write(`Usage: flow-ai-obs auth [login|logout|status]
|
|
232
|
-
`),n=1);process.exit(n);})();else if(
|
|
233
|
-
`),process.exit(1);});else if(
|
|
230
|
+
`),n=1);process.exit(n);})();else if(x==="otel-headers"){let{runOtelHeaders:t}=(wn(),P(En));t().then(e=>process.exit(e)).catch(()=>process.exit(1));}else if(x==="check")(async()=>{await(vt(),P(kt)).checkForUpdateInteractive();let{runCheck:t}=(yn(),P(Tn));process.exit(await t());})().catch(t=>{process.stderr.write(`Unexpected error: ${t.message}
|
|
231
|
+
`),process.exit(1);});else if(ai.has(x))ss();else {let{bold:t,cyan:e,dim:r}=(it(),P(Ce));process.stdout.write(`
|
|
234
232
|
`+t(" flow-ai-obs")+`
|
|
235
233
|
|
|
236
234
|
`),process.stdout.write(e(" init")+r(` Auth (if needed) + hooks + native OTEL
|
package/dist/index.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
'use strict';var child_process=require('child_process'),util=require('util'),
|
|
2
|
-
`;try{
|
|
3
|
-
`);}}var b=class extends Error{constructor(e){super(e),this.name="AuthError";}},
|
|
4
|
-
`)[0].slice(0,e).trim()}function
|
|
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
|
|
6
|
-
`),r=[],n=0,
|
|
1
|
+
'use strict';var child_process=require('child_process'),util=require('util'),I=require('fs'),ge=require('os'),x=require('path'),Ke=require('https'),qe=require('http'),crypto=require('crypto');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var I__default=/*#__PURE__*/_interopDefault(I);var ge__default=/*#__PURE__*/_interopDefault(ge);var x__default=/*#__PURE__*/_interopDefault(x);var Ke__default=/*#__PURE__*/_interopDefault(Ke);var qe__default=/*#__PURE__*/_interopDefault(qe);var Pe=Object.defineProperty;var et=(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 ft=(t,e)=>{for(var r in e)Pe(t,r,{get:e[r],enumerable:true});};var xt={};ft(xt,{MacOsKeyVaultProvider:()=>ht});var Tt,ht,Mt=dt(()=>{"use strict";Tt=util.promisify(child_process.execFile),ht=class{static async isAvailable(){try{return I.accessSync("/usr/bin/security",I.constants.X_OK),!0}catch{return !1}}async getSecret(e,r){try{let{stdout:n}=await Tt("security",["find-generic-password","-w","-a",r,"-s",e]);return n.trim()||null}catch{return null}}async setSecret(e,r,n){await Tt("security",["add-generic-password","-U","-a",r,"-s",e,"-w",n]);}async deleteSecret(e,r){try{return await Tt("security",["delete-generic-password","-a",r,"-s",e]),!0}catch{return !1}}getStoragePath(){return "macOS Keychain"}};});var Vt={};ft(Vt,{LinuxKeyVaultProvider:()=>yt});var Bt,yt,Wt=dt(()=>{"use strict";Bt=util.promisify(child_process.execFile),yt=class{static async isAvailable(){let e=["/usr/bin/secret-tool","/bin/secret-tool","/usr/local/bin/secret-tool"];for(let r of e)try{return I.accessSync(r,I.constants.X_OK),!0}catch{}return !1}async getSecret(e,r){try{let{stdout:n}=await Bt("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",u=>{u===0?i():s(new Error(`secret-tool exited with code ${u}`));}),o.stdin.write(n),o.stdin.end();});}async deleteSecret(e,r){try{return await Bt("secret-tool",["clear","service",e,"account",r]),!0}catch{return !1}}getStoragePath(){return "Linux Secret Service (libsecret)"}};});var Ht={};ft(Ht,{WindowsKeyVaultProvider:()=>At});var At,Yt=dt(()=>{"use strict";At=class{static async isAvailable(){try{return await et("keytar").getPassword("__flow_probe__","__flow_probe__"),!0}catch{return !1}}async getSecret(e,r){return et("keytar").getPassword(e,r)}async setSecret(e,r,n){await et("keytar").setPassword(e,r,n);}async deleteSecret(e,r){return et("keytar").deletePassword(e,r)}getStoragePath(){return "Windows Credential Manager"}};});var mt="https://dev.flow.ciandt.com/otel",be="https://dev.flow.ciandt.com";function D(){let t=process.env.FLOW_BASE_URL;return t&&t.trim()?t.trim():be}function Y(){let t=D();return {AUTH_ENGINE:process.env.FLOW_AUTH_ENGINE_URL||`${t}/auth-engine-api/v2/api-key/token`,GATEWAY_TRACES:`${mt}/flow-langfuse-gateway/v1/traces`,GATEWAY_HEALTH:`${mt}/flow-langfuse-gateway/v1/health`,OTEL_ENDPOINT:process.env.FLOW_OTEL_ENDPOINT_URL||`${mt}`}}Y();var rt={SERVICE:"flow-plugins-cli",ACCOUNT_TOKEN:"token-cache"},nt="FLOW-nodejs",st="config.json",gt={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",BUFFER_TTL_DAYS:"FLOW_TELEMETRY_BUFFER_TTL_DAYS",BUFFER_MAX_FILES:"FLOW_TELEMETRY_BUFFER_MAX_FILES",FLOW_USER_EMAIL:"FLOW_USER_EMAIL"};var A={FILE_PREFIX:"flow-obs-buffer-",DEFAULT_TTL_DAYS:4,MIN_TTL_DAYS:1,MAX_TTL_DAYS:30,DEFAULT_MAX_FILES:50,MIN_MAX_FILES:1,MAX_MAX_FILES:500,REPLAY_BATCH_SIZE:10},Ft="flow-ai-obs-debug.log",w={TOOL_INPUT:2e4,TOOL_OUTPUT:2e4,TRACE_OUTPUT:2e4,USER_INSTRUCTION:1e4,TRACE_INPUT:5e4};function _t(){let t=D();return {API_URL:process.env.FLOW_METRICS_URL||`${t}/metrics-collector-api/log-event`,BOOSTER:"flow-ai-obs"}}var St={credentials:"credentials","token-cache":"tokenCache"};function G(){let t=ge__default.default.homedir();if(process.platform==="darwin")return x__default.default.join(t,"Library","Preferences",nt,st);if(process.platform==="win32"){let r=process.env.APPDATA??x__default.default.join(t,"AppData","Roaming");return x__default.default.join(r,nt,st)}let e=process.env.XDG_CONFIG_HOME??x__default.default.join(t,".config");return x__default.default.join(e,nt,st)}function Et(){try{let t=I__default.default.readFileSync(G(),"utf8");return JSON.parse(t)}catch{return {}}}function Dt(t){let e=G();I__default.default.mkdirSync(x__default.default.dirname(e),{recursive:true}),I__default.default.writeFileSync(e,JSON.stringify(t,null,2),{encoding:"utf8",mode:384});}var ot=class{static isAvailable(){return true}static hasExistingData(){try{if(!I__default.default.existsSync(G()))return !1;let e=JSON.parse(I__default.default.readFileSync(G(),"utf8"));return !!(e&&e.credentials)}catch{return false}}async getSecret(e,r){let n=Et(),i=St[r]??r,s=n[i];return s?typeof s=="string"?s:JSON.stringify(s):null}async setSecret(e,r,n){let i=Et(),s=St[r]??r;if(r==="token-cache")try{i[s]=JSON.parse(n);}catch{i[s]=n;}else i[s]=n;Dt(i);}async deleteSecret(e,r){let n=Et(),i=St[r]??r;return i in n?(delete n[i],Dt(n),true):false}getStoragePath(){return `config.json (unencrypted) \u2014 ${G()}`}};async function Gt(){return await He()??new ot}async function He(){switch(process.platform){case "darwin":{let{MacOsKeyVaultProvider:t}=await Promise.resolve().then(()=>(Mt(),xt));return await t.isAvailable()?new t:null}case "linux":{let{LinuxKeyVaultProvider:t}=await Promise.resolve().then(()=>(Wt(),Vt));return await t.isAvailable()?new t:null}case "win32":{let{WindowsKeyVaultProvider:t}=await Promise.resolve().then(()=>(Yt(),Ht));return await t.isAvailable()?new t:null}default:return null}}var Jt=rt.SERVICE,jt=rt.ACCOUNT_TOKEN,Ot=null;function Kt(){return Ot||(Ot=Gt()),Ot}async function wt(t){await(await Kt()).setSecret(Jt,jt,JSON.stringify({accessToken:t.accessToken,expiresAt:t.expiresAt,lastAuthCheckAt:t.lastAuthCheckAt}));}async function kt(){let e=await(await Kt()).getSecret(Jt,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 Lt(){let t=await kt();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 je=x.join(ge.tmpdir(),Ft);function a(...t){if(process.env[_.FLOW_OBS_DEBUG]!=="1")return;let e=`[${new Date().toISOString()}] ${t.join(" ")}
|
|
2
|
+
`;try{I.writeFileSync(je,e,{flag:"a"});}catch(r){process.stderr.write(`[flow-obs debug ERROR] ${r.message}
|
|
3
|
+
`);}}var b=class extends Error{constructor(e){super(e),this.name="AuthError";}},Xe=/^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$|^[a-z0-9]$/;function ze(t){if(!Xe.test(t))throw new Error(`Invalid tenant value: "${t}". Tenant must be lowercase alphanumeric and hyphens (1-64 chars).`)}var qt={INVALID_CLIENT_SECRET:"Invalid Client Secret \u2014 check the value and try again",INVALID_CLIENT_ID:"Invalid Client ID \u2014 check the value and try again",INVALID_TENANT:"Invalid Tenant \u2014 check the value and try again",TENANT_NOT_FOUND:"Tenant not found \u2014 verify the tenant identifier"};function Ze(t,e){let r=e.length>400?e.slice(0,400)+"\u2026":e;a("toAuthError",`status=${t} body=${r}`);try{let n=JSON.parse(e);if(typeof n.error=="string"&&(a("toAuthError",`api_error_code=${n.error}`+(n.message?` api_message=${n.message}`:"")),qt[n.error]))return new b(qt[n.error])}catch{}return t===401||t===403||t===500?new b("Invalid credentials"):t>=400&&t<500?new b("Authentication request was rejected"):new Error("Authentication service unavailable, please try again later")}function j(t){return new Promise((e,r)=>{try{ze(t.tenant);}catch(p){return r(p)}let n=JSON.stringify({clientSecret:t.clientSecret}),i=new URL(Y().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?Ke__default.default:qe__default.default).request(o,p=>{let S=[];p.on("data",E=>S.push(E)),p.on("end",()=>{let E=S.join("");if((p.statusCode??0)>=400)return r(Ze(p.statusCode??0,E));let m;try{m=JSON.parse(E);}catch{return r(new Error("Invalid response from auth engine"))}let g=m.expires_at??new Date(Date.now()+(m.expires_in??3600)*1e3).toISOString();e({accessToken:m.access_token??"",expiresAt:g});});});l.on("error",p=>r(new Error(`Network error: ${p.message}`))),l.write(n),l.end();})}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 er(t){return tr.some(e=>e.test(t))}function rr(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 at(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 it(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&&er(e.hostname))throw new Error(`SSRF: private/loopback host not allowed: ${e.hostname}`);return t}async function Xt(){let t=at(process.env[_.ANTHROPIC_AUTH_TOKEN]);return t?{user:await Lt().catch(()=>null)??t.clientId,tenant:t.tenant}:{user:"",tenant:""}}function nr(){return new Date().toISOString().slice(0,10)}async function sr(t){let e=nr(),r=await kt();if(r?.lastAuthCheckAt!==e){a("getOrRefreshToken",`daily auth check (last: ${r?.lastAuthCheckAt??"never"})`);try{let s=await j(t);try{await wt({...s,lastAuthCheckAt:e});}catch{}return a("getOrRefreshToken",`daily check passed, expires=${s.expiresAt}`),s.accessToken}catch(s){if(s instanceof b)throw s;a("getOrRefreshToken",`daily check network error \u2014 using cache: ${s.message}`);}}let n=r!=null&&new Date(r.expiresAt)>new Date;if(a("getOrRefreshToken",`cacheValid=${n}`),n)return a("getOrRefreshToken",`using cached token, expires=${r.expiresAt}`),r.accessToken;a("getOrRefreshToken",`token expired \u2014 refreshing via auth-engine (tenant=${t.tenant} clientId=${t.clientId})`);let i=await j(t);try{await wt({...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 or(t,e){let r=e&&e.accessToken?e.accessToken:"";return {endpoint:t.replace(/\/$/,"")+"/flow-langfuse-gateway/v1/traces",authHeader:`Bearer ${r}`}}function ir(t,e,r){let n=Buffer.from(`${e}:${r}`).toString("base64");return {endpoint:t.replace(/\/$/,"")+"/api/public/otel/v1/traces",authHeader:`Basic ${n}`}}async function v(){let t=[],e=process.env[_.ANTHROPIC_MODEL]??"",r=at(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],u=process.env[_.LANGFUSE_SECRET_KEY];if(i&&s&&o&&u){let m="",g=n;r&&(m=await Lt().catch(()=>null)??r.clientId);let T={user:m??"",tenant:g??"",team:"",project:"",model:e};t.push({mode:"direct",...ir(it(s),o,u),...T}),a("resolveCredentials","direct mode active",`user=${T.user}`,`tenant=${T.tenant}`);}if(!r){if(t.length===0){let m=[];return m.authError=false,m}return t}let l;try{l=await sr(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 S={user:rr(l)??r.clientId,tenant:n,team:"",project:"",model:e},E=process.env[_.FLOW_TELEMETRY_GATEWAY]??D();return t.push({mode:"gateway",...or(it(E),{accessToken:l}),...S}),t}async function zt(){return (await v()).length>0}function Zt(){let t=process.env[_.FLOW_USER_EMAIL];if(t)return a("resolveUserEmail",`using FLOW_USER_EMAIL override: ${t}`),t;try{let e=ge__default.default.userInfo().username||process.env.USERNAME||process.env.USER||"",r=e.lastIndexOf("\\");if(r!==-1&&(e=e.slice(r+1)),e=e.trim().replace(/[^a-zA-Z0-9._%+\-]/g,""),!e)return a("resolveUserEmail","username empty after sanitisation \u2014 omitting x-flow-user"),console.warn("[flow-ai-obs] Could not derive x-flow-user: username is empty. Set FLOW_USER_EMAIL to fix this."),null;let n=`${e}@ciandt.com`;return a("resolveUserEmail",`derived email: ${n}`),n}catch(e){return a("resolveUserEmail",`os.userInfo() threw: ${e.message} \u2014 omitting x-flow-user`),console.warn("[flow-ai-obs] Could not derive x-flow-user from OS username. Set FLOW_USER_EMAIL to fix this."),null}}function k(t,e){let r=typeof t=="object"?JSON.stringify(t):String(t??"");return r.length>e?r.slice(0,e)+" \u2026[truncated]":r}function ct(t,e=100){return String(t??"").split(`
|
|
4
|
+
`)[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 O(t){process.stdout.write(JSON.stringify(t));}var Rt=()=>crypto.randomBytes(16).toString("hex"),U=()=>crypto.randomBytes(8).toString("hex");function L(){return String(BigInt(Date.now())*1000000n)}var gr=/^[0-9a-f-]{1,64}$/i,_r=x.normalize(ge.tmpdir())+x.sep;function Sr(t,e){let r=x.resolve(t);if(!r.startsWith(e))throw new Error(`Path traversal detected: ${t}`);return r}function Nt(t){if(!gr.test(t))throw new Error(`Invalid session ID: ${t}`);return Sr(x.join(ge.tmpdir(),`flow-obs-${t}.json`),_r)}function M(t){let e=Nt(t);if(!I.existsSync(e))return null;try{return JSON.parse(I.readFileSync(e,"utf8"))}catch{return null}}function B(t,e){I.writeFileSync(Nt(t),JSON.stringify(e),{encoding:"utf8",mode:384});}function Pt(t){try{I.unlinkSync(Nt(t));}catch{}}function ne(t){if(!t||!I.existsSync(t))return null;try{let e=I.readFileSync(t,"utf8").trimEnd().split(`
|
|
5
|
+
`);for(let r=e.length-1;r>=0;r--)try{let n=JSON.parse(e[r]);if(n.type==="user"&&n.uuid)return n.uuid}catch{}}catch{}return null}function bt(t){if(!t||!I.existsSync(t))return null;try{let e=I.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(S=>S.type==="text").map(S=>S.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(`
|
|
7
7
|
|
|
8
|
-
`),inputTokens:n,outputTokens:
|
|
9
|
-
`)[0].match(/^\/([a-z][a-z0-9-]*(?::[a-z][a-z0-9-]*)?)(?:\s.*)?$/i)?.[1]??null}var
|
|
10
|
-
`);return}let n=!!(await
|
|
11
|
-
`,{flag:"a",encoding:"utf8",mode:384}),a("sendTraces:dump",`request appendada em ${
|
|
12
|
-
${
|
|
13
|
-
${r}`},{re:/\b(AKIA[0-9A-Z]{16})\b/g,replace:()=>`AKIA${
|
|
14
|
-
`)),
|
|
15
|
-
`),process.stdout.write(JSON.stringify(e));}}
|
|
8
|
+
`),inputTokens:n,outputTokens:i}}catch{}return null}var yr=new Set([".venv","__pycache__",".git","node_modules"]),Ar=new Set([".pyc",".pyo"]),Or=new Set(["SKILL.md",".DS_Store",".gitignore"]);function ie(t){return t.replace(":","/")}function lt(t,e){if(!t)return null;let r=ie(t),n=[x.join(ge.homedir(),".claude","skills",r,"SKILL.md"),x.join(e??"",".claude","skills",r,"SKILL.md")];for(let i of n)if(I.existsSync(i))try{return I.readFileSync(i,"utf8")}catch{}return null}function ae(t){return t.split(`
|
|
9
|
+
`)[0].match(/^\/([a-z][a-z0-9-]*(?::[a-z][a-z0-9-]*)?)(?:\s.*)?$/i)?.[1]??null}var wr=new Set(["Read","Write","Edit","MultiEdit","Bash","Glob","Grep","TodoWrite","WebFetch","WebSearch","Agent","Task"]);function ce(t){return !!t.slashSkill||t.toolCalls.some(n=>n.tool==="Skill")?t.toolCalls.some(n=>n.tool==="Skill"&&!n.synthetic||wr.has(n.tool))?"complete":"prerequisite_required":null}function ut(t,e){if(!t)return null;let r=ie(t),n=[x.join(ge.homedir(),".claude","skills",r),x.join(e??"",".claude","skills",r)],i=null;for(let u of n)if(I.existsSync(x.join(u,"SKILL.md"))){i=u;break}if(!i)return null;let s=[];function o(u,l){for(let p of I.readdirSync(u,{withFileTypes:true})){if(yr.has(p.name)||Or.has(p.name)||Ar.has(x.extname(p.name)))continue;let S=l?`${l}/${p.name}`:p.name;p.isDirectory()?o(x.join(u,p.name),S):s.push(S);}}return o(i,""),s.length>0?s:null}function Ir(t){try{let e=t.split(".")[1].replace(/-/g,"+").replace(/_/g,"/");return JSON.parse(Buffer.from(e,"base64").toString())}catch{return null}}function Rr(t,e,r,n){return new Promise(i=>{let s=new URL(t),o=s.protocol==="https:",u=(o?Ke__default.default:qe__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);});u.on("error",()=>i(0)),u.setTimeout(5e3,()=>{u.destroy(),i(0);}),u.write(e),u.end();})}async function C(t,e={}){try{let r=at(process.env[_.ANTHROPIC_AUTH_TOKEN]);if(!r)return;let n,i=new Promise((E,m)=>{n=setTimeout(()=>m(new Error("getToken timeout")),4e3),n.unref();}),{accessToken:s}=await Promise.race([j(r),i]);clearTimeout(n);let o=Ir(s);if(!o)return;let u=o.tenant||r.tenant,l=JSON.stringify({action:t,booster:_t().BOOSTER,metadata:e,success:!0,tenant:u,timestamp:new Date().toISOString(),os:process.platform,user:{email:o.email||"",id:o.sub||"",name:o.name||o.email||""}}),p=it(_t().API_URL),S=await Rr(p,l,s,u);a("metrics.logEvent",`action=${t} status=${S}`);}catch(r){a("metrics.logEvent",`silenced error: ${r.message}`);}}var Nr=`\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 auth login`;async function vt(t,e=false){if(e){process.stdout.write(JSON.stringify({decision:"block",reason:Nr})+`
|
|
10
|
+
`);return}let n=!!(await v()).authError,i=t.session_id||"unknown",s=t.prompt||"",o=t.cwd||"",u=ne(t.transcript_path)||Rt(),l=ae(s),p=l?lt(l,o):null,S=l?ut(l,o):null;B(i,{traceId:Rt(),spanId:U(),startNs:L(),sessionId:i,prompt:s,cwd:o,traceName:u,transcriptPath:t.transcript_path||"",model:process.env[_.ANTHROPIC_MODEL]||"",toolCalls:[],spans:[],pendingTool:null,slashSkill:l,skillContent:p,skillArtifacts:S}),C("SESSION_STARTED",{traceType:l?"skill":"prompt",slashSkill:l,clientIdExpired:n}),a("UserPromptSubmit",`sid=${i}`,`traceName=${u}`,`slashSkill=${l}`),O(t);}async function le(t){let e=t.session_id||"unknown",r=t.tool_name||"unknown",n=t.tool_input||{},i=M(e);i&&(i.pendingTool={name:r,inputStr:k(n,w.TOOL_INPUT),startNs:L()},B(e,i)),a("PreToolUse",`sid=${e}`,`tool=${r}`,`stateFound=${!!i}`),O(t);}var Pr={name:gt.SCOPE_NAME,version:gt.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 c(t,e){return e==null||e===""?null:{key:t,value:{stringValue:String(e)}}}function $(...t){return t.filter(e=>e!==null)}function ue(t,e){return {resourceSpans:[{resource:{attributes:t},scopeSpans:[{scope:Pr,spans:Array.isArray(e)?e:[e]}]}]}}var pe=x.join(ge.tmpdir(),"flow-obs-requests.ndjson");function de(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{I.writeFileSync(pe,s+`
|
|
11
|
+
`,{flag:"a",encoding:"utf8",mode:384}),a("sendTraces:dump",`request appendada em ${pe}`);}catch(o){a("sendTraces:dump",`falha ao salvar: ${o.message}`);}}function Fr(t){let e=new URL(t),r=new URL(Y().GATEWAY_HEALTH);return r.hostname=e.hostname,r.port=e.port,r.protocol=e.protocol,r}function fe(t,e){return new Promise((r,n)=>{let i=t._isSSL?Ke__default.default:qe__default.default;t.headers=Object.assign({},t.headers,{Connection:"close"});let s=i.request(t,o=>{let u=[];o.on("data",l=>u.push(l)),o.on("end",()=>r({statusCode:o.statusCode??0,body:u.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 me(t){let e;try{e=Fr(t);}catch{return false}let r=e.protocol==="https:";try{let n=await fe({hostname:e.hostname,port:e.port||(r?443:80),path:e.pathname,method:"GET",_isSSL:r},null);return a("checkHealth",`url=${e.href} status=${n.statusCode}`),n.statusCode>=200&&n.statusCode<300}catch{return false}}async function pt(t,e){let r=JSON.stringify(t),n=new URL(e),i=n.protocol==="https:",s={"Content-Type":"application/json","Content-Length":Buffer.byteLength(r),"x-flow-user":Zt()??"","x-flow-api-key":"Basic czNjcjN0LXA0c3N3MHJk"};a("sendTraces:request",`POST ${e}`),a("sendTraces:request",`headers=${JSON.stringify(s)}`),a("sendTraces:request",`body=${r.slice(0,500)}${r.length>500?"\u2026":""}`);try{let o=await fe({hostname:n.hostname,port:n.port||(i?443:80),path:n.pathname,method:"POST",headers:s,_isSSL:i},r);return a("sendTraces:response",`status=${o.statusCode}`),de(e,s,r,o.statusCode,o.body),o.statusCode}catch(o){return a("sendTraces:error",o.message),de(e,s,r,0,o.message),0}}function Dr(){let t=parseInt(process.env[_.BUFFER_TTL_DAYS]??"",10);return (Number.isFinite(t)?Math.max(A.MIN_TTL_DAYS,Math.min(A.MAX_TTL_DAYS,t)):A.DEFAULT_TTL_DAYS)*24*60*60*1e3}function xr(){let t=parseInt(process.env[_.BUFFER_MAX_FILES]??"",10);return Number.isFinite(t)?Math.max(A.MIN_MAX_FILES,Math.min(A.MAX_MAX_FILES,t)):A.DEFAULT_MAX_FILES}function _e(t){if(/[/\\]/.test(t))throw new Error(`Invalid buffer fileId: ${t}`);return x__default.default.join(ge__default.default.tmpdir(),`${A.FILE_PREFIX}${t}.json`)}function Ct(){let t=ge__default.default.tmpdir(),e;try{e=I__default.default.readdirSync(t);}catch{return []}return e.filter(r=>r.startsWith(A.FILE_PREFIX)&&r.endsWith(".json")).map(r=>{let n=x__default.default.join(t,r),i=0;try{i=I__default.default.statSync(n).mtimeMs;}catch{}return {full:n,mtime:i}}).sort((r,n)=>r.mtime-n.mtime).map(r=>r.full)}function K(t){try{let e=xr(),r=Ct();if(r.length>=e){let s=r.slice(0,r.length-e+1);for(let o of s)try{I__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 I__default.default.writeFileSync(_e(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 Se(t){let e=Ct(),r=t,n=[];for(let i of e){if(n.length>=r)break;try{let s=I__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 Ee(t){try{I__default.default.unlinkSync(_e(t)),a("buffer",`deleted fileId=${t}`);}catch{}}function Te(){let t=Date.now()-Dr();for(let e of Ct())try{let{mtimeMs:r}=I__default.default.statSync(e);r<t&&(I__default.default.unlinkSync(e),a("buffer",`evicted stale: ${x__default.default.basename(e)}`));}catch{}}async function Mr(t){Te();let e=Se(A.REPLAY_BATCH_SIZE);e.length&&(a("replayBufferedTraces",`replaying ${e.length} buffered trace(s)`),await Promise.allSettled(e.map(async r=>{try{let n=await pt(r.payload,t.endpoint);n>=200&&n<300?(Ee(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 he(t){let e=await v();if(!e.length)return e.authError&&(a("postToLangfuse","auth refresh failed \u2014 buffering trace"),K(t)),0;let r=await Promise.all(e.map(async s=>{if(s.mode!=="gateway")return {creds:s,healthy:true};let o=await me(s.endpoint);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 Mr(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"),K(t),0;let l=await pt(t,s.endpoint);return (l===0||l>=500)&&(a("postToLangfuse",`gateway send failed (status ${l}) \u2014 buffering trace`),K(t)),l}let u=await pt(t,s.endpoint);return (u===0||u>=500)&&(a("postToLangfuse",`direct endpoint unavailable (status ${u}) \u2014 buffering trace`),K(t)),u}))).find(s=>s!==0)??0}var y="[REDACTED]",Br="[REDACTED-EMAIL]",Vr="[REDACTED-CPF]",Wr="[REDACTED-CNPJ]",ye="[REDACTED-PHONE]",Hr=[{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:()=>Br},{re:/\b\d{3}\.\d{3}\.\d{3}-\d{2}\b/g,replace:()=>Vr},{re:/\b\d{2}\.\d{3}\.\d{3}\/\d{4}-\d{2}\b/g,replace:()=>Wr},{re:/\(\d{2}\)\s?\d{4,5}[-\s]?\d{4}/g,replace:()=>ye},{re:/\+55[\s-]?\d{2}[\s-]?\d{4,5}[-\s]?\d{4}/g,replace:()=>ye}];function R(t){if(t==null)return "";let e=typeof t=="string"?t:JSON.stringify(t);return Hr.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=M(e);if(!o){O(t);return}let u=L(),l=o.pendingTool,p=l?.name===r,S=p?l.startNs:String(BigInt(u)-200000000n),E=p?l.inputStr:k(n,w.TOOL_INPUT),m=E,g=null;if(r==="Skill"){let tt=typeof n=="object"&&n!==null?n.skill||n.name||n.skillName||n.commandName||String(Object.values(n)[0]??""):String(n);g=tt?String(tt).trim():null;let N=g?lt(g,o.cwd):null;N&&(m=N,o.skillContent||(o.skillContent=N),o.skillArtifacts||(o.skillArtifacts=ut(g,o.cwd))),g&&!o.slashSkill&&(o.slashSkill=g),a("PostToolUse","Skill tool detected",`skillName=${g}`,`contentFound=${!!N}`);}let T=R(k(s,w.TOOL_OUTPUT)),h=/\b(error|exception|failed|failure|traceback|errno)\b/i.test(T.slice(0,500)),q=h?"ERROR":"DEFAULT",W=U(),X=Math.round(Number(BigInt(u)-BigInt(S))/1e6),Z={Agent:"AGENT",Task:"AGENT"}[r]??"TOOL",Q=r==="Skill"&&g?g:ct(E,60);o.toolCalls.push({tool:r,brief:Q,error:h,durationMs:X});let H=o.spans;H.push({traceId:o.traceId,spanId:W,parentSpanId:o.spanId,name:r,kind:3,startTimeUnixNano:S,endTimeUnixNano:u,attributes:$(c(f.OBS_NAME,r),c(f.OBS_TYPE,Z),c(f.OBS_LEVEL,q),c(f.OBS_INPUT,R(m)),c(f.OBS_OUTPUT,T),c("tool.name",r),c("tool.error",String(h)),r==="Skill"&&g?c("skill.name",g):null,r==="Skill"?c("skill.invocation","slash-command"):null),status:{code:h?2:1}}),o.pendingTool=null,B(e,o),h&&C("TOOL_ERROR",{toolName:r}),a("PostToolUse",`sid=${e}`,`tool=${r}`,`error=${h}`,`durationMs=${X}`,`totalSpans=${H.length}`),O(t);}var Oe={"claude-opus-4-6":{input:15,output:75},"claude-opus-4-5":{input:15,output:75},"claude-sonnet-4-6":{input:3,output:15},"claude-sonnet-4-5":{input:3,output:15},"claude-haiku-4-5":{input:.8,output:4},"claude-4-6-opus":{input:15,output:75},"claude-4-6-sonnet":{input:3,output:15},"claude-4-5-opus":{input:15,output:75},"claude-4-5-sonnet":{input:3,output:15},"claude-4-5-haiku":{input:.8,output:4},"claude-3-5-sonnet-20241022":{input:3,output:15},"claude-3-5-haiku-20241022":{input:.8,output:4},"claude-3-opus-20240229":{input:15,output:75}};function we(t,e,r){let n=Object.keys(Oe).find(o=>(t??"").toLowerCase().includes(o));if(!n)return;let i=Oe[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=M(e);if(!n){O(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 Xt(),o=n.toolCalls,u=n.spans;if(n.slashSkill&&!o.some(d=>d.tool==="Skill")){let d=U(),P=n.skillContent?n.skillContent:JSON.stringify({skill:n.slashSkill});o.push({tool:"Skill",brief:n.slashSkill,error:false,durationMs:0,synthetic:true}),u.push({traceId:n.traceId,spanId:d,parentSpanId:n.spanId,name:"Skill",kind:3,startTimeUnixNano:n.startNs,endTimeUnixNano:n.startNs,attributes:$(c(f.OBS_NAME,"Skill"),c(f.OBS_TYPE,"TOOL"),c(f.OBS_LEVEL,"DEFAULT"),c(f.OBS_INPUT,P),c(f.OBS_OUTPUT,"loaded via slash command"),c("tool.name","Skill"),c("tool.error","false"),c("skill.name",n.slashSkill),c("skill.invocation","slash-command")),status:{code:1}}),a("Stop",`slashSkill=${n.slashSkill}`,"synthetic span injected");}let l=t.transcript_path||n.transcriptPath||"",p=bt(l);if(l&&(o.some(d=>d.tool==="Skill"&&!d.synthetic)||!!n.slashSkill)&&!p?.text){await new Promise(P=>setTimeout(P,500));let d=bt(l);d?.text&&(p=d);}a("Stop",`transcriptPath=${l||"(empty)"}`,`assistantOut=${p?`text=${p.text.length}chars`:"null"}`);let E=o.length,m=o.filter(d=>d.error).length,g=R(p?.text?k(p.text,w.TRACE_OUTPUT):E===0?"No tools used":o.map((d,P)=>`${P+1}. ${d.tool}${d.brief?` \u2192 ${d.brief}`:""}${d.error?" [ERROR]":""}`).join(`
|
|
14
|
+
`)),T=p?.inputTokens??0,h=p?.outputTokens??0,q=o.map((d,P)=>`${P+1}. ${d.tool}${d.brief?` \u2192 ${d.brief}`:""}${d.error?" [ERROR]":""} (${d.durationMs}ms)`),W=!!(n.slashSkill||o.some(d=>d.tool==="Skill")),X=o.some(d=>d.tool==="Agent");if(!W&&!X){a("Stop",`sid=${e}`,"skipping trace \u2014 no Skill or Agent calls found"),C("TRACE_SKIPPED",{reason:"no_skill_or_agent"}),Pt(e),O(t);return}let z=W?"skill":"agent",Z=Math.round(Number(BigInt(i)-BigInt(n.startNs))/1e6),Q=we(n.model,T,h),F=ce(n);F==="prerequisite_required"&&p?.text&&(F="complete"),F==="prerequisite_required"&&(u.push({traceId:n.traceId,spanId:U(),parentSpanId:n.spanId,name:"prerequisite-check",kind:3,startTimeUnixNano:n.startNs,endTimeUnixNano:i,attributes:$(c(f.OBS_NAME,"prerequisite-check"),c(f.OBS_TYPE,"EVENT"),c(f.OBS_LEVEL,"WARNING"),c(f.OBS_OUTPUT,g),c("skill.name",n.slashSkill||void 0),c("execution_status","prerequisite_required")),status:{code:1}}),a("Stop",`sid=${e}`,"prerequisite-check span injected",`skill=${n.slashSkill}`));let H=(()=>{if(!(!W||!n.prompt)){if(n.slashSkill){let d=n.prompt.replace(new RegExp(`^\\/${n.slashSkill}\\s*`,"i"),"").trim();return d?k(R(d),w.USER_INSTRUCTION):void 0}return k(R(n.prompt),w.USER_INSTRUCTION)||void 0}})(),tt=JSON.stringify({trace_type:z,...F!==null&&{execution_status:F},...n.slashSkill?{skill_name:n.slashSkill}:{},...n.skillArtifacts?.length&&{skill_artifacts:n.skillArtifacts},...H!==void 0&&{user_instruction:H},latency_ms:Z,...T&&{tokens_input:T},...h&&{tokens_output:h},cost_usd:Q,...n.model?{model:n.model}:{},toolCount:E,errorCount:m,stopReason:r,sessionId:n.sessionId,tools:q.length?q:void 0}),N=R(k(n.prompt,w.TRACE_INPUT)),Le=$(c(f.TRACE_NAME,n.traceName),c(f.TRACE_INPUT,N),c(f.TRACE_OUTPUT,g),c(f.OBS_INPUT,N),c(f.OBS_OUTPUT,g),c(f.TRACE_METADATA,tt),c(f.SESSION_ID,n.sessionId),c(f.USER_ID,s.user),c(f.OBS_TYPE,"GENERATION"),c(f.MODEL,n.model),T?c(f.INPUT_TOKENS,T):null,h?c(f.OUTPUT_TOKENS,h):null,c("claude.stop_reason",r),c("claude.tool_count",String(E)),c("claude.error_count",String(m)),c("claude.session_id",n.sessionId),c("flow.trace_type",z),{key:f.TRACE_TAGS,value:{arrayValue:{values:[{stringValue:z}]}}}),Ie={traceId:n.traceId,spanId:n.spanId,name:n.traceName,kind:1,startTimeUnixNano:n.startNs,endTimeUnixNano:i,attributes:Le,status:{code:m>0?2:1}},Re=$(c("service.name",process.env.LANGFUSE_PROJECT_NAME||"claude-code"),c("deployment.environment",process.env.LANGFUSE_ENVIRONMENT||"default")),$t=[...u,Ie];a("Stop",`sid=${e}`,`totalTools=${E}`,`errorTools=${m}`,`spans=${$t.length}`,`inputTokens=${T}`,`outputTokens=${h}`,`traceOutput="${ct(g,80)}"`);let Ne=await he(ue(Re,$t));a("Stop",`POST status=${Ne}`,`traceId=${n.traceId}`),C("TRACE_SENT",{latencyMs:Z,totalTools:E,errorTools:m,inputTokens:T,outputTokens:h,costUsd:Q}),Pt(e),O(t);}async function Yr(){let t=process.argv[2];if(t==="UserPromptSubmit"){let r=await It(),n;try{n=await v();}catch{process.stdout.write(JSON.stringify(r));return}n.authError?await vt(r,true):n.length>0?await vt(r):process.stdout.write(JSON.stringify(r));return}if(!await zt()){let r=[];process.stdin.on("data",n=>r.push(n)),process.stdin.on("end",()=>process.stdout.write(r.join("")));return}let e=await It();switch(t){case "PreToolUse":await le(e);break;case "PostToolUse":await Ae(e);break;case "Stop":await ke(e);break;default:process.stderr.write(`[flow-obs] unknown event: ${t}
|
|
15
|
+
`),process.stdout.write(JSON.stringify(e));}}Yr().catch(t=>{process.stderr.write(`[flow-obs] fatal: ${t.message}
|
|
16
16
|
`),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'),l=require('os'),qe=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 l__namespace=/*#__PURE__*/_interopNamespace(l);var qe__default=/*#__PURE__*/_interopDefault(qe);var _e=Object.defineProperty;var _=(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 A=(e,t,r)=>()=>{if(r)throw r[0];try{return e&&(t=e(e=0)),t}catch(n){throw r=[n],n}};var Te=(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)_e(e,r,{get:t[r],enumerable:true});};var Q={};L(Q,{MacOsKeyVaultProvider:()=>F});var b,F,ee=A(()=>{"use strict";b=util.promisify(child_process.execFile),F=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 b("security",["find-generic-password","-w","-a",r,"-s",t]);return n.trim()||null}catch{return null}}async setSecret(t,r,n){await b("security",["add-generic-password","-U","-a",r,"-s",t,"-w",n]);}async deleteSecret(t,r){try{return await b("security",["delete-generic-password","-a",r,"-s",t]),!0}catch{return !1}}getStoragePath(){return "macOS Keychain"}};});var re={};L(re,{LinuxKeyVaultProvider:()=>$});var te,$,ne=A(()=>{"use strict";te=util.promisify(child_process.execFile),$=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 te("secret-tool",["lookup","service",t,"account",r]);return n.trim()||null}catch{return null}}async setSecret(t,r,n){await new Promise((o,s)=>{let a=child_process.spawn("secret-tool",["store","--label",t,"service",t,"account",r]);a.on("error",s),a.on("close",m=>{m===0?o():s(new Error(`secret-tool exited with code ${m}`));}),a.stdin.write(n),a.stdin.end();});}async deleteSecret(t,r){try{return await te("secret-tool",["clear","service",t,"account",r]),!0}catch{return !1}}getStoragePath(){return "Linux Secret Service (libsecret)"}};});var oe={};L(oe,{WindowsKeyVaultProvider:()=>D});var D,se=A(()=>{"use strict";D=class{static async isAvailable(){try{return await _("keytar").getPassword("__flow_probe__","__flow_probe__"),!0}catch{return !1}}async getSecret(t,r){return _("keytar").getPassword(t,r)}async setSecret(t,r,n){await _("keytar").setPassword(t,r,n);}async deleteSecret(t,r){return _("keytar").deletePassword(t,r)}getStoragePath(){return "Windows Credential Manager"}};});var fe=Te((pr,Xe)=>{Xe.exports={name:"@ciandt-flow/flow-ai-obs",version:"0.7.0-beta.537",description:"Claude Code hooks for Langfuse OTLP tracing \u2014 cross-platform",main:"dist/index.js",bin:{"flow-ai-obs":"dist/cli.js","flow-ai-obs-setup":"dist/setup.js"},scripts:{build:"tsup",test:"jest",typecheck:"tsc --noEmit",lint:"eslint src bin scripts",format:'prettier --write "src/**/*.ts" "bin/**/*.ts" "scripts/**/*.ts"',"format:check":'prettier --check "src/**/*.ts" "bin/**/*.ts" "scripts/**/*.ts"',"security-scan":"trufflehog filesystem src/ --fail --no-update --exclude-paths .trufflehogignore",postinstall:`node -e "require('fs').existsSync('dist/setup.js') && require('child_process').execFileSync(process.execPath, ['dist/setup.js'], {stdio:'inherit'})"`,prepublishOnly:"npm run security-scan && npm run build","release:npm":"changeset publish",changeset:"changeset","version-packages":"changeset version","install:hooks":"node dist/cli.js install","auth:login":"node dist/cli.js auth login","auth:logout":"node dist/cli.js auth logout","auth:status":"node dist/cli.js auth status",smoke:"bash scripts/smoke-test.sh","smoke:debug":"bash scripts/smoke-test.sh --debug","smoke:send":"bash scripts/smoke-test.sh --send --allow-http --debug"},files:["dist/","README.md","LICENSE.md"],keywords:["claude-code","langfuse","observability","otlp","hooks","flow","ciandt"],author:"CI&T Flow Team",license:"SEE LICENSE IN LICENSE.md",private:!1,dependencies:{},optionalDependencies:{keytar:"7.9.0"},devDependencies:{"@changesets/changelog-github":"^0.6.0","@changesets/cli":"^2.30.0","@types/jest":"^30.0.0","@types/node":"^25.8.0",jest:"^30.4.2","ts-jest":"^29.4.9",tsup:"^8.5.1","eslint-config-prettier":"^10.1.5",prettier:"^3.5.3",typescript:"^6.0.3","typescript-eslint":"^8.33.0"},engines:{node:">=18.0.0"},overrides:{esbuild:"^0.28.1"},publishConfig:{registry:"https://registry.npmjs.org",access:"public"},repository:{type:"git",url:"git+https://github.com/CI-T-HyperX/flow-codeassistant-observability.git"}};});!process.env.NO_COLOR&&process.stdout.isTTY;function R(){return process.platform==="win32"?false:process.getuid?.()===0}function Y(){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:l__namespace.homedir(),username:process.env.SUDO_USER||process.env.USER||l__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 f__namespace.join(t,".claude","settings.json")}return f__namespace.join(l__namespace.homedir(),".claude","settings.json")}if(process.platform==="win32"){let e=process.env.USERPROFILE||l__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(l__namespace.homedir(),".claude","settings.json")}var j="flow-ai-obs",G="config.json";function ve(){if(process.platform==="win32"){let r=process.env.APPDATA||f__namespace.join(l__namespace.homedir(),"AppData","Roaming");return f__namespace.join(r,j,G)}let e=Y(),t=process.env.XDG_CONFIG_HOME||f__namespace.join(e.home,".config");return f__namespace.join(t,j,G)}function Ae(){try{let e=i__namespace.readFileSync(ve(),"utf8");return JSON.parse(e)}catch{return {}}}function B(){let{baseUrl:e}=Ae();return typeof e!="string"||e.trim()===""?null:e.trim().replace(/\/$/,"")}var Le="https://dev.flow.ciandt.com/otel";function I(){return B()??process.env.FLOW_BASE_URL??Le}function C(){let e=I();return {AUTH_ENGINE:process.env.FLOW_AUTH_ENGINE_URL||`${e}/auth-engine-api/v2/api-key/token`,GATEWAY_TRACES:process.env.FLOW_OTEL_ENDPOINT_URL||`${e}/flow-langfuse-gateway/v1/traces`,GATEWAY_HEALTH:process.env.FLOW_OTEL_ENDPOINT_URL||`${e}/flow-langfuse-gateway/v1/health`,OTEL_ENDPOINT:process.env.FLOW_OTEL_ENDPOINT_URL||`${e}`}}var Re=C(),S={SERVICE:"flow-plugins-cli",ACCOUNT_CREDS:"credentials"},w="FLOW-nodejs",O="config.json";function J(){let e=I();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-sonnet",CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS:"1"}}var K={CLAUDE_CODE_ENABLE_TELEMETRY:"1",OTEL_EXPORTER_OTLP_ENDPOINT:Re.OTEL_ENDPOINT,OTEL_EXPORTER_OTLP_PROTOCOL:"http/json",OTEL_METRICS_EXPORTER:"otlp",OTEL_LOGS_EXPORTER:"otlp",OTEL_LOG_TOOL_DETAILS:"1",OTEL_LOG_USER_PROMPTS:"1"},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_MODEL:"ANTHROPIC_MODEL",ANTHROPIC_AUTH_TOKEN:"ANTHROPIC_AUTH_TOKEN",FLOW_OBS_DEBUG:"FLOW_TELEMETRY_DEBUG",FLOW_OBS_ALLOW_HTTP:"FLOW_TELEMETRY_ALLOW_HTTP",BUFFER_TTL_DAYS:"FLOW_TELEMETRY_BUFFER_TTL_DAYS",BUFFER_MAX_FILES:"FLOW_TELEMETRY_BUFFER_MAX_FILES",FLOW_USER_EMAIL:"FLOW_USER_EMAIL"};var X={LOCK_STALE_MS:3e4},q={UserPromptSubmit:5,PreToolUse:3,PostToolUse:10,Stop:15};var z="flow-ai-obs-debug.log";var N={credentials:"credentials","token-cache":"tokenCache"};function h(){let e=l__namespace.default.homedir();if(process.platform==="darwin")return f__namespace.default.join(e,"Library","Preferences",w,O);if(process.platform==="win32"){let r=process.env.APPDATA??f__namespace.default.join(e,"AppData","Roaming");return f__namespace.default.join(r,w,O)}let t=process.env.XDG_CONFIG_HOME??f__namespace.default.join(e,".config");return f__namespace.default.join(t,w,O)}function U(){try{let e=i__namespace.default.readFileSync(h(),"utf8");return JSON.parse(e)}catch{return {}}}function Z(e){let t=h();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 v=class{static isAvailable(){return true}static hasExistingData(){try{if(!i__namespace.default.existsSync(h()))return !1;let t=JSON.parse(i__namespace.default.readFileSync(h(),"utf8"));return !!(t&&t.credentials)}catch{return false}}async getSecret(t,r){let n=U(),o=N[r]??r,s=n[o];return s?typeof s=="string"?s:JSON.stringify(s):null}async setSecret(t,r,n){let o=U(),s=N[r]??r;if(r==="token-cache")try{o[s]=JSON.parse(n);}catch{o[s]=n;}else o[s]=n;Z(o);}async deleteSecret(t,r){let n=U(),o=N[r]??r;return o in n?(delete n[o],Z(n),true):false}getStoragePath(){return `config.json (unencrypted) \u2014 ${h()}`}};async function ie(){return await xe()??new v}async function xe(){switch(process.platform){case "darwin":{let{MacOsKeyVaultProvider:e}=await Promise.resolve().then(()=>(ee(),Q));return await e.isAvailable()?new e:null}case "linux":{let{LinuxKeyVaultProvider:e}=await Promise.resolve().then(()=>(ne(),re));return await e.isAvailable()?new e:null}case "win32":{let{WindowsKeyVaultProvider:e}=await Promise.resolve().then(()=>(se(),oe));return await e.isAvailable()?new e:null}default:return null}}var Me=S.SERVICE,He=S.ACCOUNT_CREDS,x=null;function Ve(){return x||(x=ie()),x}async function M(){let t=await(await Ve()).getSecret(Me,He);if(!t)return null;try{return JSON.parse(t)}catch{return null}}f.join(l.tmpdir(),z);function ae(e){if(!e)return null;try{let t=e.split(".");if(t.length<2)return null;let r=JSON.parse(Buffer.from(t[1].replace(/-/g,"+").replace(/_/g,"/"),"base64").toString("utf8")),{clientId:n,clientSecret:o,tenant:s}=r;return !n||!o||!s?null:{clientId:n,clientSecret:o,tenant:s}}catch{return null}}function ce(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}.`}var Be=X.LOCK_STALE_MS;function le(e){try{let t=i__namespace.statSync(e);Date.now()-t.mtimeMs>Be&&i__namespace.unlinkSync(e);}catch{}try{i__namespace.writeFileSync(e,String(process.pid),{flag:"wx"});}catch(t){throw t.code==="EEXIST"?new Error("Another install is already in progress. If this is stale, remove: "+e):t}}function ue(e){try{i__namespace.unlinkSync(e);}catch{}}function Je(e,t){let n=(Array.isArray(e)?e:[]).map(o=>{if(!Array.isArray(o?.hooks))return null;let s=o.hooks.filter(a=>!a.command?.startsWith?.("flow-ai-obs "));return s.length>0?{...o,hooks:s}:null}).filter(o=>o!=null);return [t,...n]}function pe(){let e=P(),t=e+".lock",r=[];i__namespace.mkdirSync(f__namespace.dirname(e),{recursive:true}),le(t);try{if(i__namespace.existsSync(e)){i__namespace.copyFileSync(e,e+".bkp");try{i__namespace.chmodSync(e+".bkp",384);}catch{}}let n={};try{n=JSON.parse(i__namespace.readFileSync(e,"utf8"));}catch{}let o=n.env&&typeof n.env=="object"?n.env:{};delete o.OTEL_EXPORTER_OTLP_HEADERS,n.env={...o,...K,...J()},n.otelHeadersHelper="flow-ai-obs otel-headers",(!n.hooks||typeof n.hooks!="object"||Array.isArray(n.hooks))&&(n.hooks={});let s=(c,y)=>({matcher:"",hooks:[{type:"command",command:`flow-ai-obs ${c}`,timeout:y}]}),a=["UserPromptSubmit","PreToolUse","PostToolUse","Stop"],m=n.hooks;for(let c of a){let y=Je(m[c],s(c,q[c]));y.length>1&&r.push(c),m[c]=y;}i__namespace.writeFileSync(e,JSON.stringify(n,null,2)+`
|
|
3
|
-
`,{encoding:"utf8",mode:384});try{i__namespace.chmodSync(e,384);}catch{}}finally{
|
|
4
|
-
`,{encoding:"utf8",mode:384});try{i__namespace.chmodSync(t,384);}catch{}}finally{
|
|
2
|
+
'use strict';var child_process=require('child_process'),util=require('util'),i=require('fs'),u=require('path'),l=require('os'),Xe=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 u__namespace=/*#__PURE__*/_interopNamespace(u);var l__namespace=/*#__PURE__*/_interopNamespace(l);var Xe__default=/*#__PURE__*/_interopDefault(Xe);var _e=Object.defineProperty;var S=(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 A=(e,t,r)=>()=>{if(r)throw r[0];try{return e&&(t=e(e=0)),t}catch(n){throw r=[n],n}};var Te=(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)_e(e,r,{get:t[r],enumerable:true});};var K={};L(K,{MacOsKeyVaultProvider:()=>b});var C,b,X=A(()=>{"use strict";C=util.promisify(child_process.execFile),b=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 C("security",["find-generic-password","-w","-a",r,"-s",t]);return n.trim()||null}catch{return null}}async setSecret(t,r,n){await C("security",["add-generic-password","-U","-a",r,"-s",t,"-w",n]);}async deleteSecret(t,r){try{return await C("security",["delete-generic-password","-a",r,"-s",t]),!0}catch{return !1}}getStoragePath(){return "macOS Keychain"}};});var z={};L(z,{LinuxKeyVaultProvider:()=>U});var q,U,Z=A(()=>{"use strict";q=util.promisify(child_process.execFile),U=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 q("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",E=>{E===0?s():o(new Error(`secret-tool exited with code ${E}`));}),a.stdin.write(n),a.stdin.end();});}async deleteSecret(t,r){try{return await q("secret-tool",["clear","service",t,"account",r]),!0}catch{return !1}}getStoragePath(){return "Linux Secret Service (libsecret)"}};});var Q={};L(Q,{WindowsKeyVaultProvider:()=>F});var F,ee=A(()=>{"use strict";F=class{static async isAvailable(){try{return await S("keytar").getPassword("__flow_probe__","__flow_probe__"),!0}catch{return !1}}async getSecret(t,r){return S("keytar").getPassword(t,r)}async setSecret(t,r,n){await S("keytar").setPassword(t,r,n);}async deleteSecret(t,r){return S("keytar").deletePassword(t,r)}getStoragePath(){return "Windows Credential Manager"}};});var me=Te((lr,Ke)=>{Ke.exports={name:"@ciandt-flow/flow-ai-obs",version:"0.7.0-beta.552",description:"Claude Code hooks for Langfuse OTLP tracing \u2014 cross-platform",main:"dist/index.js",bin:{"flow-ai-obs":"dist/cli.js","flow-ai-obs-setup":"dist/setup.js"},scripts:{build:"tsup",test:"jest",typecheck:"tsc --noEmit",lint:"eslint src bin scripts",format:'prettier --write "src/**/*.ts" "bin/**/*.ts" "scripts/**/*.ts"',"format:check":'prettier --check "src/**/*.ts" "bin/**/*.ts" "scripts/**/*.ts"',"security-scan":"trufflehog filesystem src/ --fail --no-update --exclude-paths .trufflehogignore",postinstall:`node -e "require('fs').existsSync('dist/setup.js') && require('child_process').execFileSync(process.execPath, ['dist/setup.js'], {stdio:'inherit'})"`,prepublishOnly:"npm run security-scan && npm run build","release:npm":"changeset publish",changeset:"changeset","version-packages":"changeset version","install:hooks":"node dist/cli.js install","auth:login":"node dist/cli.js auth login","auth:logout":"node dist/cli.js auth logout","auth:status":"node dist/cli.js auth status",smoke:"bash scripts/smoke-test.sh","smoke:debug":"bash scripts/smoke-test.sh --debug","smoke:send":"bash scripts/smoke-test.sh --send --allow-http --debug"},files:["dist/","README.md","LICENSE.md"],keywords:["claude-code","langfuse","observability","otlp","hooks","flow","ciandt"],author:"CI&T Flow Team",license:"SEE LICENSE IN LICENSE.md",private:!1,dependencies:{},optionalDependencies:{keytar:"7.9.0"},devDependencies:{"@changesets/changelog-github":"^0.6.0","@changesets/cli":"^2.30.0","@types/jest":"^30.0.0","@types/node":"^25.8.0",jest:"^30.4.2","ts-jest":"^29.4.9",tsup:"^8.5.1","eslint-config-prettier":"^10.1.5",prettier:"^3.5.3",typescript:"^6.0.3","typescript-eslint":"^8.33.0"},engines:{node:">=18.0.0"},overrides:{esbuild:"^0.28.1"},publishConfig:{registry:"https://registry.npmjs.org",access:"public"},repository:{type:"git",url:"git+https://github.com/CI-T-HyperX/flow-codeassistant-observability.git"}};});var R="https://dev.flow.ciandt.com/otel",we="https://dev.flow.ciandt.com";function k(){let e=process.env.FLOW_BASE_URL;return e&&e.trim()?e.trim():we}function P(){let e=k();return {AUTH_ENGINE:process.env.FLOW_AUTH_ENGINE_URL||`${e}/auth-engine-api/v2/api-key/token`,GATEWAY_TRACES:`${R}/flow-langfuse-gateway/v1/traces`,GATEWAY_HEALTH:`${R}/flow-langfuse-gateway/v1/health`,OTEL_ENDPOINT:process.env.FLOW_OTEL_ENDPOINT_URL||`${R}`}}var ve=P(),_={SERVICE:"flow-plugins-cli",ACCOUNT_CREDS:"credentials"},T="FLOW-nodejs",w="config.json";function j(){let e=k();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-sonnet",CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS:"1"}}var Y={CLAUDE_CODE_ENABLE_TELEMETRY:"1",OTEL_EXPORTER_OTLP_ENDPOINT:ve.OTEL_ENDPOINT,OTEL_EXPORTER_OTLP_PROTOCOL:"http/json",OTEL_METRICS_EXPORTER:"otlp",OTEL_LOGS_EXPORTER:"otlp",OTEL_LOG_TOOL_DETAILS:"1",OTEL_LOG_USER_PROMPTS:"1"},f={FLOW_TELEMETRY:"FLOW_TELEMETRY",FLOW_TELEMETRY_GATEWAY:"FLOW_TELEMETRY_GATEWAY_URL",LANGFUSE_BASE_URL:"LANGFUSE_BASE_URL",LANGFUSE_PUBLIC_KEY:"LANGFUSE_PUBLIC_KEY",LANGFUSE_SECRET_KEY:"LANGFUSE_SECRET_KEY",ANTHROPIC_MODEL:"ANTHROPIC_MODEL",ANTHROPIC_AUTH_TOKEN:"ANTHROPIC_AUTH_TOKEN",FLOW_OBS_DEBUG:"FLOW_TELEMETRY_DEBUG",FLOW_OBS_ALLOW_HTTP:"FLOW_TELEMETRY_ALLOW_HTTP",BUFFER_TTL_DAYS:"FLOW_TELEMETRY_BUFFER_TTL_DAYS",BUFFER_MAX_FILES:"FLOW_TELEMETRY_BUFFER_MAX_FILES",FLOW_USER_EMAIL:"FLOW_USER_EMAIL"};var G={LOCK_STALE_MS:3e4},W={UserPromptSubmit:5,PreToolUse:3,PostToolUse:10,Stop:15};var B="flow-ai-obs-debug.log";var I={credentials:"credentials","token-cache":"tokenCache"};function m(){let e=l__namespace.default.homedir();if(process.platform==="darwin")return u__namespace.default.join(e,"Library","Preferences",T,w);if(process.platform==="win32"){let r=process.env.APPDATA??u__namespace.default.join(e,"AppData","Roaming");return u__namespace.default.join(r,T,w)}let t=process.env.XDG_CONFIG_HOME??u__namespace.default.join(e,".config");return u__namespace.default.join(t,T,w)}function N(){try{let e=i__namespace.default.readFileSync(m(),"utf8");return JSON.parse(e)}catch{return {}}}function J(e){let t=m();i__namespace.default.mkdirSync(u__namespace.default.dirname(t),{recursive:true}),i__namespace.default.writeFileSync(t,JSON.stringify(e,null,2),{encoding:"utf8",mode:384});}var v=class{static isAvailable(){return true}static hasExistingData(){try{if(!i__namespace.default.existsSync(m()))return !1;let t=JSON.parse(i__namespace.default.readFileSync(m(),"utf8"));return !!(t&&t.credentials)}catch{return false}}async getSecret(t,r){let n=N(),s=I[r]??r,o=n[s];return o?typeof o=="string"?o:JSON.stringify(o):null}async setSecret(t,r,n){let s=N(),o=I[r]??r;if(r==="token-cache")try{s[o]=JSON.parse(n);}catch{s[o]=n;}else s[o]=n;J(s);}async deleteSecret(t,r){let n=N(),s=I[r]??r;return s in n?(delete n[s],J(n),true):false}getStoragePath(){return `config.json (unencrypted) \u2014 ${m()}`}};async function te(){return await Ue()??new v}async function Ue(){switch(process.platform){case "darwin":{let{MacOsKeyVaultProvider:e}=await Promise.resolve().then(()=>(X(),K));return await e.isAvailable()?new e:null}case "linux":{let{LinuxKeyVaultProvider:e}=await Promise.resolve().then(()=>(Z(),z));return await e.isAvailable()?new e:null}case "win32":{let{WindowsKeyVaultProvider:e}=await Promise.resolve().then(()=>(ee(),Q));return await e.isAvailable()?new e:null}default:return null}}var Fe=_.SERVICE,$e=_.ACCOUNT_CREDS,$=null;function De(){return $||($=te()),$}async function re(){let t=await(await De()).getSecret(Fe,$e);if(!t)return null;try{return JSON.parse(t)}catch{return null}}u.join(l.tmpdir(),B);!process.env.NO_COLOR&&process.stdout.isTTY;function D(){return process.platform==="win32"?false:process.getuid?.()===0}function ne(){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:l__namespace.homedir(),username:process.env.SUDO_USER||process.env.USER||l__namespace.userInfo().username}}function O(){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 u__namespace.join(t,".claude","settings.json")}return u__namespace.join(l__namespace.homedir(),".claude","settings.json")}if(process.platform==="win32"){let e=process.env.USERPROFILE||l__namespace.homedir();return u__namespace.join(e,".claude","settings.json")}if(process.platform==="linux"&&process.getuid?.()===0&&process.env.SUDO_USER){let t=child_process.spawnSync("getent",["passwd",process.env.SUDO_USER],{encoding:"utf8",timeout:5e3}).stdout?.split(":")[5]?.trim();if(t)return u__namespace.join(t,".claude","settings.json")}return u__namespace.join(l__namespace.homedir(),".claude","settings.json")}var se="flow-ai-obs",oe="config.json";function ae(){if(process.platform==="win32"){let r=process.env.APPDATA||u__namespace.join(l__namespace.homedir(),"AppData","Roaming");return u__namespace.join(r,se,oe)}let e=ne(),t=process.env.XDG_CONFIG_HOME||u__namespace.join(e.home,".config");return u__namespace.join(t,se,oe)}function ce(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 le(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}.`}var We=G.LOCK_STALE_MS;function ue(e){try{let t=i__namespace.statSync(e);Date.now()-t.mtimeMs>We&&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 Be(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 de(){let e=O(),t=e+".lock",r=[];i__namespace.mkdirSync(u__namespace.dirname(e),{recursive:true}),ue(t);try{if(i__namespace.existsSync(e)){i__namespace.copyFileSync(e,e+".bkp");try{i__namespace.chmodSync(e+".bkp",384);}catch{}}let n=ae();if(i__namespace.existsSync(n)){let c=n+".bkp";i__namespace.copyFileSync(n,c);try{i__namespace.chmodSync(c,384);}catch{}}let s={};try{s=JSON.parse(i__namespace.readFileSync(e,"utf8"));}catch{}let o=s.env&&typeof s.env=="object"?s.env:{};delete o.OTEL_EXPORTER_OTLP_HEADERS,s.env={...o,...Y,...j()},s.otelHeadersHelper="flow-ai-obs otel-headers",(!s.hooks||typeof s.hooks!="object"||Array.isArray(s.hooks))&&(s.hooks={});let a=(c,y)=>({matcher:"",hooks:[{type:"command",command:`flow-ai-obs ${c}`,timeout:y}]}),E=["UserPromptSubmit","PreToolUse","PostToolUse","Stop"],V=s.hooks;for(let c of E){let y=Be(V[c],a(c,W[c]));y.length>1&&r.push(c),V[c]=y;}i__namespace.writeFileSync(e,JSON.stringify(s,null,2)+`
|
|
3
|
+
`,{encoding:"utf8",mode:384});try{i__namespace.chmodSync(e,384);}catch{}}finally{pe(t);}return {settingsPath:e,preserved:r}}function fe(e){let t=O(),r=t+".lock";i__namespace.mkdirSync(u__namespace.dirname(t),{recursive:true}),ue(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{pe(r);}}var H;function he(){return H||(H=me()),H}var Ee=u__namespace.default.join(l__namespace.default.tmpdir(),"flow-obs-update-cache.json"),Ze=1440*60*1e3,Qe=3e3;function et(e,t){let r=o=>{let a=String(o).replace(/^v/,"").match(/^(\d+)\.(\d+)\.(\d+)/);return a?[+a[1],+a[2],+a[3]]:null},n=r(e),s=r(t);return !n||!s?false:s[0]!==n[0]?s[0]>n[0]:s[1]!==n[1]?s[1]>n[1]:s[2]>n[2]}function tt(){try{let e=JSON.parse(i__namespace.default.readFileSync(Ee,"utf8"));return typeof e.latestVersion!="string"||Date.now()-e.checkedAt>=Ze?null:e}catch{return null}}function rt(e,t,r=Date.now()){try{i__namespace.default.writeFileSync(Ee,JSON.stringify({latestVersion:e,updatePriority:t??null,checkedAt:r}),{mode:384});}catch{}}function nt(e){let t=he().name,r=Xe__default.default.get(`https://registry.npmjs.org/${encodeURIComponent(t)}/latest`,{timeout:Qe},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 ye(){try{if(tt())return;setImmediate(()=>{nt((e,t)=>{e||!t||et(he().version,t.version)&&rt(t.version,t.updatePriority,0);});});}catch{}}var st=u__namespace.default.resolve(__dirname,".."),ot=process.env.INIT_CWD?u__namespace.default.resolve(process.env.INIT_CWD):null;ot===st&&process.exit(0);D()&&(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
|
|
8
|
+
`),process.exit(1));async function it(){try{de();}catch{}let e=await re();if(!e){process.stderr.write(`
|
|
9
9
|
[flow-ai-obs] No credentials found.
|
|
10
10
|
Run \`flow-ai-obs auth login\` to authenticate and enable telemetry.
|
|
11
11
|
|
|
12
|
-
`);return}let t=
|
|
12
|
+
`);return}let t=ce(process.env[f.ANTHROPIC_AUTH_TOKEN]);if(!t||t.clientId!==e.clientId||t.clientSecret!==e.clientSecret||t.tenant!==e.tenant)try{let n=le(e);fe({[f.ANTHROPIC_AUTH_TOKEN]:n});}catch{}}it().catch(()=>{}).finally(()=>ye());
|