@ciandt-flow/flow-ai-obs 0.7.0-beta.552 → 0.7.0-beta.555
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 +78 -78
- package/dist/index.js +11 -11
- package/dist/setup.js +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,57 +1,57 @@
|
|
|
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 Ue=require('readline/promises'),Es=require('https'),g=require('fs'),dt=require('os'),Rt=require('path'),child_process=require('child_process'),Ns=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 Ue__namespace=/*#__PURE__*/_interopNamespace(Ue);var Es__default=/*#__PURE__*/_interopDefault(Es);var g__namespace=/*#__PURE__*/_interopNamespace(g);var dt__namespace=/*#__PURE__*/_interopNamespace(dt);var Rt__namespace=/*#__PURE__*/_interopNamespace(Rt);var Ns__default=/*#__PURE__*/_interopDefault(Ns);var Ce=Object.defineProperty;var us=Object.getOwnPropertyDescriptor;var ds=Object.getOwnPropertyNames;var ps=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 fs=(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)Ce(t,r,{get:e[r],enumerable:true});},ms=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of ds(e))!ps.call(t,s)&&s!==r&&Ce(t,s,{get:()=>e[s],enumerable:!(n=us(e,s))||n.enumerable});return t};var P=t=>ms(Ce({},"__esModule",{value:true}),t);var ce=fs((ui,gs)=>{gs.exports={name:"@ciandt-flow/flow-ai-obs",version:"0.7.0-beta.555",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 Ne={};W(Ne,{bold:()=>b,cyan:()=>I,dim:()=>w,green:()=>L,red:()=>R,yellow:()=>_});function _t(t,e){return hs?r=>`\x1B[${t}m${r}\x1B[${e}m`:r=>r}var hs,L,R,_,I,b,w,it=m(()=>{"use strict";hs=!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 le(t,e){let r=Ue__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 ue(t,e){let r=Ue__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 $e=m(()=>{"use strict";});var vt={};W(vt,{checkForUpdate:()=>vs,checkForUpdateInteractive:()=>As,fetchLatestVersionAsync:()=>Lr,isNewer:()=>Ot,primeUpdateCache:()=>ks});function C(){return Fe||(Fe=ce()),Fe}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 Me(){try{let t=JSON.parse(g__namespace.default.readFileSync(kr,"utf8"));return typeof t.latestVersion!="string"||Date.now()-t.checkedAt>=Ts?null:t}catch{return null}}function Be(t,e,r=Date.now()){try{g__namespace.default.writeFileSync(kr,JSON.stringify({latestVersion:t,updatePriority:e??null,checkedAt:r}),{mode:384});}catch{}}function He(t){let e=C().name,r=Es__default.default.get(`https://registry.npmjs.org/${encodeURIComponent(e)}/latest`,{timeout:ys},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 xe(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 De(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
|
|
12
|
+
`),child_process.spawn("npm",["install","-g",`${e}@${t}`],{detached:true,stdio:"ignore",windowsHide:true}).unref();}async function _s(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
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
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(
|
|
19
|
-
`),d(O));}let
|
|
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(A),h.close(),process.stderr.write(`
|
|
19
|
+
`),d(O));}let A=setTimeout(()=>S(false),e);h.once("line",O=>S(O.trim().toLowerCase()==="y")),h.once("close",()=>S(false));})}async function Os(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
|
-
`;try{g.writeFileSync(
|
|
28
|
-
`);}}var
|
|
26
|
+
`),r();});})}function Lr(){return new Promise(t=>{He((e,r)=>t(e||!r?null:r));})}function vs(){try{let t=Me();if(t){Ot(C().version,t.latestVersion)&&(t.updatePriority==="auto"?De(t.latestVersion):xe(t.latestVersion));return}setImmediate(()=>{He((e,r)=>{e||!r||(Be(r.version,r.updatePriority),Ot(C().version,r.version)&&(r.updatePriority==="auto"?De(r.version):xe(r.version)));});});}catch{}}async function As(t={}){try{let e=Me();if(e){if(!Ot(C().version,e.latestVersion))return}else {let n=await Lr();if(!n||(Be(n.version,n.updatePriority),!Ot(C().version,n.version)))return;e={latestVersion:n.version,updatePriority:n.updatePriority,checkedAt:Date.now()};}if(e.updatePriority==="auto"){De(e.latestVersion);return}if(!at()){xe(e.latestVersion);return}await _s(e.latestVersion,t.timeoutMs)&&await Os(e.latestVersion);}catch{}}function ks(){try{if(Me())return;setImmediate(()=>{He((t,e)=>{t||!e||Ot(C().version,e.version)&&Be(e.version,e.updatePriority,0);});});}catch{}}var Fe,kr,Ts,ys,At=m(()=>{"use strict";$e();kr=Rt__namespace.default.join(dt__namespace.default.tmpdir(),"flow-obs-update-cache.json"),Ts=1440*60*1e3,ys=3e3;});function ct(){let t=process.env.FLOW_BASE_URL;return t&&t.trim()?t.trim():Dt}function kt(){let t=ct();return {AUTH_ENGINE:process.env.FLOW_AUTH_ENGINE_URL||`${t}/auth-engine-api/v2/api-key/token`,GATEWAY_TRACES:`${je}/flow-langfuse-gateway/v1/traces`,GATEWAY_HEALTH:`${je}/flow-langfuse-gateway/v1/health`,OTEL_ENDPOINT:process.env.FLOW_OTEL_ENDPOINT_URL||`${je}`}}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 Ye(){let t=ct();return {API_URL:process.env.FLOW_METRICS_URL||`${t}/metrics-collector-api/log-event`,BOOSTER:"flow-ai-obs"}}var je,Dt,Ls,de,pe,fe,We,V,p,Rr,Ve,D,Ir,Y,v=m(()=>{"use strict";je="https://dev.flow.ciandt.com/otel",Dt="https://dev.flow.ciandt.com";Ls=kt(),de={SERVICE:"flow-plugins-cli",ACCOUNT_CREDS:"credentials",ACCOUNT_TOKEN:"token-cache"},pe="FLOW-nodejs",fe="config.json",We={SCOPE_NAME:"flow-ai-obs",SCOPE_VERSION:"0.1.0"};V={CLAUDE_CODE_ENABLE_TELEMETRY:"1",OTEL_EXPORTER_OTLP_ENDPOINT:Ls.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"},Rr={LOCK_STALE_MS:3e4,CONNECTIVITY_MAX_RETRY:3,CONNECTIVITY_RETRY_MS:2e3},Ve={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},Ir="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(bs,e,{flag:"a"});}catch(r){process.stderr.write(`[flow-obs debug ERROR] ${r.message}
|
|
28
|
+
`);}}var bs,M=m(()=>{"use strict";v();bs=Rt.join(dt.tmpdir(),Ir);});function $s(t){if(!Us.test(t))throw new Error(`Invalid tenant value: "${t}". Tenant must be lowercase alphanumeric and hyphens (1-64 chars).`)}function Fs(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}`:"")),Pr[n.error]))return new lt(Pr[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{$s(t.tenant);}catch(u){return r(u)}let n=JSON.stringify({clientSecret:t.clientSecret}),s=new URL(kt().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?Es__default.default:Ns__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(Fs(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,Us,Pr,Bt=m(()=>{"use strict";v();M();lt=class extends Error{constructor(e){super(e),this.name="AuthError";}},Us=/^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$|^[a-z0-9]$/;Pr={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 br(){return process.platform==="win32"?false:process.getuid?.()===0}function ut(){if(br())return process.stderr.write(`
|
|
29
29
|
`+R(` \u2717 flow-ai-obs is not supported in a sudo context.
|
|
30
30
|
|
|
31
31
|
`)+I(` npm install -g @ciandt-flow/flow-ai-obs
|
|
32
32
|
`)+`
|
|
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{
|
|
35
|
-
`,{encoding:"utf8",mode:384});try{g__namespace.chmodSync(e,384);}catch{}}finally{
|
|
36
|
-
`,{encoding:"utf8",mode:384});try{g__namespace.chmodSync(t,384);}catch{}}finally{
|
|
37
|
-
`,{encoding:"utf8",mode:384});try{g__namespace.chmodSync(e,384);}catch{}}finally{
|
|
33
|
+
`),1}var Ht=m(()=>{"use strict";it();});function Cr(){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 k(){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 me=m(()=>{"use strict";Ht();});function ge(){if(process.platform==="win32"){let r=process.env.APPDATA||Rt__namespace.join(dt__namespace.homedir(),"AppData","Roaming");return Rt__namespace.join(r,Nr,Ur)}let t=Cr(),e=process.env.XDG_CONFIG_HOME||Rt__namespace.join(t.home,".config");return Rt__namespace.join(e,Nr,Ur)}function Wt(){try{let t=g__namespace.readFileSync(k(),"utf8"),r=JSON.parse(t).env?.FLOW_BASE_URL;return typeof r=="string"&&r.trim()?r.trim():null}catch{return null}}function Fr(){try{let t=g__namespace.readFileSync(k(),"utf8");return JSON.parse(t).env??null}catch{return null}}var Nr,Ur,Je=m(()=>{"use strict";me();Nr="flow-ai-obs",Ur="config.json";});function Vt(){let t=dt__namespace.default.homedir();if(process.platform==="darwin")return Rt__namespace.default.join(t,"Library","Preferences",pe,fe);if(process.platform==="win32"){let r=process.env.APPDATA??Rt__namespace.default.join(t,"AppData","Roaming");return Rt__namespace.default.join(r,pe,fe)}let e=process.env.XDG_CONFIG_HOME??Rt__namespace.default.join(t,".config");return Rt__namespace.default.join(e,pe,fe)}function Xe(){try{let t=g__namespace.default.readFileSync(Vt(),"utf8");return JSON.parse(t)}catch{return {}}}function xr(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 qe,he,Dr=m(()=>{"use strict";v();qe={credentials:"credentials","token-cache":"tokenCache"};he=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=Xe(),s=qe[r]??r,o=n[s];return o?typeof o=="string"?o:JSON.stringify(o):null}async setSecret(e,r,n){let s=Xe(),o=qe[r]??r;if(r==="token-cache")try{s[o]=JSON.parse(n);}catch{s[o]=n;}else s[o]=n;xr(s);}async deleteSecret(e,r){let n=Xe(),s=qe[r]??r;return s in n?(delete n[s],xr(n),!0):!1}getStoragePath(){return `config.json (unencrypted) \u2014 ${Vt()}`}};});var Mr={};W(Mr,{MacOsKeyVaultProvider:()=>Ze});var ze,Ze,Br=m(()=>{"use strict";ze=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 ze("security",["find-generic-password","-w","-a",r,"-s",e]);return n.trim()||null}catch{return null}}async setSecret(e,r,n){await ze("security",["add-generic-password","-U","-a",r,"-s",e,"-w",n]);}async deleteSecret(e,r){try{return await ze("security",["delete-generic-password","-a",r,"-s",e]),!0}catch{return !1}}getStoragePath(){return "macOS Keychain"}};});var jr={};W(jr,{LinuxKeyVaultProvider:()=>Qe});var Hr,Qe,Wr=m(()=>{"use strict";Hr=util.promisify(child_process.execFile),Qe=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 Hr("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 Hr("secret-tool",["clear","service",e,"account",r]),!0}catch{return !1}}getStoragePath(){return "Linux Secret Service (libsecret)"}};});var Vr={};W(Vr,{WindowsKeyVaultProvider:()=>tr});var tr,Yr=m(()=>{"use strict";tr=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 Gr(){return await Ks()??new he}async function Ks(){switch(process.platform){case "darwin":{let{MacOsKeyVaultProvider:t}=await Promise.resolve().then(()=>(Br(),Mr));return await t.isAvailable()?new t:null}case "linux":{let{LinuxKeyVaultProvider:t}=await Promise.resolve().then(()=>(Wr(),jr));return await t.isAvailable()?new t:null}case "win32":{let{WindowsKeyVaultProvider:t}=await Promise.resolve().then(()=>(Yr(),Vr));return await t.isAvailable()?new t:null}default:return null}}var Kr=m(()=>{"use strict";Dr();});function Xr(){return er||(er=Gr()),er}async function Gt(t){await(await Xr()).setSecret(Jr,qr,JSON.stringify({accessToken:t.accessToken,expiresAt:t.expiresAt,lastAuthCheckAt:t.lastAuthCheckAt}));}async function It(){let e=await(await Xr()).getSecret(Jr,qr);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 It();return t?new Date(t.expiresAt)>new Date:false}async function Kt(){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,zi,qr,er,we=m(()=>{"use strict";Kr();v();Jr=de.SERVICE,zi=de.ACCOUNT_CREDS,qr=de.ACCOUNT_TOKEN,er=null;});function Xs(t){return qs.some(e=>e.test(t))}function zs(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 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 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&&Xs(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 Kt().catch(()=>null)??t.clientId,tenant:t.tenant}:{user:"",tenant:""}}function Zs(){return new Date().toISOString().slice(0,10)}async function Qs(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 to(t,e){let r=e&&e.accessToken?e.accessToken:"";return {endpoint:t.replace(/\/$/,"")+"/flow-langfuse-gateway/v1/traces",authHeader:`Bearer ${r}`}}function eo(t,e,r){let n=Buffer.from(`${e}:${r}`).toString("base64");return {endpoint:t.replace(/\/$/,"")+"/api/public/otel/v1/traces",authHeader:`Basic ${n}`}}async function K(){let t=[],e=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 Kt().catch(()=>null)??r.clientId);let A={user:E??"",tenant:S??"",team:"",project:"",model:e};t.push({mode:"direct",...eo(pt(o),i,a),...A}),l("resolveCredentials","direct mode active",`user=${A.user}`,`tenant=${A.tenant}`);}if(!r){if(t.length===0){let E=[];return E.authError=false,E}return t}let c;try{c=await Qs(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:zs(c)??r.clientId,tenant:n,team:"",project:"",model:e},h=process.env[p.FLOW_TELEMETRY_GATEWAY]??ct();return t.push({mode:"gateway",...to(pt(h),{accessToken:c}),...d}),t}async function Qr(){return (await K()).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}}function Jt(){return process.env.OTEL_EXPORTER_OTLP_HEADERS??null}var qs,N=m(()=>{"use strict";we();Bt();v();M();qs=[/^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 Se(t){try{let e=g__namespace.statSync(t);Date.now()-e.mtimeMs>ro&&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 Te(t){try{g__namespace.unlinkSync(t);}catch{}}function tn(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 en(){let t=k(),e=t+".lock",r=[];g__namespace.mkdirSync(Rt__namespace.dirname(t),{recursive:true}),Se(e);try{if(g__namespace.existsSync(t)){g__namespace.copyFileSync(t,t+".bkp");try{g__namespace.chmodSync(t+".bkp",384);}catch{}}let n=ge();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=tn(c[u],i(u,Ve[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{Te(e);}return {settingsPath:t,preserved:r}}function Pt(t){try{let e=g__namespace.readFileSync(k(),"utf8"),n=JSON.parse(e).env?.[t];return typeof n=="string"?n:null}catch{return null}}function H(t){let e=k(),r=e+".lock";g__namespace.mkdirSync(Rt__namespace.dirname(e),{recursive:true}),Se(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{Te(r);}}function rn(){let t=k(),e=t+".lock",r=[];g__namespace.mkdirSync(Rt__namespace.dirname(t),{recursive:true}),Se(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=tn(i[a],s(a,Ve[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{Te(e);}return {settingsPath:t,preserved:r}}function nn(t){let e=k(),r=e+".lock";g__namespace.mkdirSync(Rt__namespace.dirname(e),{recursive:true}),Se(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{Te(r);}}var ro,Xt=m(()=>{"use strict";v();Bt();me();Je();N();ro=Rr.LOCK_STALE_MS;});function ye(){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 nr(){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:
|
|
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 ${
|
|
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",rr],{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 ${rr}`:`Try with elevated permissions:
|
|
42
|
+
sudo npm install -g ${rr}`}:{success:false,error:"unknown",message:s||"npm install failed"}}var rr,sr=m(()=>{"use strict";rr="@anthropic-ai/claude-code";});function or(){return Rt__namespace.default.join(dt__namespace.default.homedir(),".claude","flow-obs",".logged-out")}function an(){try{let t=or();g__namespace.default.mkdirSync(Rt__namespace.default.dirname(t),{recursive:!0}),g__namespace.default.writeFileSync(t,"",{mode:384});}catch{}}function cn(){try{g__namespace.default.unlinkSync(or());}catch{}}function ir(){try{return g__namespace.default.existsSync(or())}catch{return false}}var ln=m(()=>{"use strict";});var ar={};W(ar,{promptRaw:()=>X,runLogin:()=>mt,runLogout:()=>co,runStatus:()=>lo});function z(t){return typeof t=="string"?t.replace(so,""):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
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
|
|
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 un(t){let{accessToken:e,expiresAt:r}=await q(t),n=zr(t);H({[p.ANTHROPIC_AUTH_TOKEN]:n}),cn(),await Gt({accessToken:e,expiresAt:r});}async function oo(t){try{return await un(t),process.stdout.write(L(` \u2713 Setup complete. Tenant: ${z(t.tenant)}
|
|
45
45
|
|
|
46
46
|
`)),0}catch(e){return process.stderr.write(R(` \u2717 Authentication failed: ${z(e.message)}
|
|
47
|
-
`)),1}}async function
|
|
47
|
+
`)),1}}async function io(){try{process.stdout.write(`
|
|
48
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
|
|
49
|
+
`)),1;try{await un({clientId:t,clientSecret:e,tenant:r});}catch(n){return process.stderr.write(R(` \u2717 Authentication failed: ${z(n.message)}
|
|
50
50
|
`)),1}return process.stdout.write(L(` \u2713 Setup complete. Tenant: ${z(r)}
|
|
51
51
|
`)),process.stdout.write(` Storage: ANTHROPIC_AUTH_TOKEN (settings.json)
|
|
52
52
|
|
|
53
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
|
|
54
|
+
`)),1}}async function mt(t={}){let e=ut();if(e)return e;if(t.clientId&&t.clientSecret&&t.tenant)return oo({clientId:t.clientId,clientSecret:t.clientSecret,tenant:t.tenant});let n=ir()?null:B(Pt(p.ANTHROPIC_AUTH_TOKEN)??process.env[p.ANTHROPIC_AUTH_TOKEN]);if(n){process.stdout.write(`
|
|
55
55
|
`),process.stdout.write(b(` Already authenticated
|
|
56
56
|
`)),process.stdout.write(w(" Tenant: ")+z(n.tenant)+`
|
|
57
57
|
`),process.stdout.write(w(" Client ID: ")+z(n.clientId)+`
|
|
@@ -61,46 +61,46 @@
|
|
|
61
61
|
|
|
62
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
|
|
64
|
+
`)),0}try{return await io()}catch(s){if(s.message==="SIGINT")return process.stdout.write(`
|
|
65
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
|
|
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 ao(){try{return process.stdout.write(`
|
|
67
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 n=await
|
|
69
|
+
`),130;throw t}}async function co(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 ao();if(n!==null)return n}try{return nn([p.ANTHROPIC_AUTH_TOKEN]),delete process.env[p.ANTHROPIC_AUTH_TOKEN],an(),process.stdout.write(L(` \u2713 Credentials removed successfully
|
|
71
71
|
`)),0}catch{return process.stderr.write(R(` \u2717 Error removing credentials
|
|
72
|
-
`)),1}}async function
|
|
72
|
+
`)),1}}async function lo(){if(ir())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 Ee())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
73
|
`+b(` Authenticated
|
|
74
74
|
`)),process.stdout.write(w(" Tenant: ")+z(t.tenant)+`
|
|
75
75
|
`),process.stdout.write(w(" Client ID: ")+z(t.clientId)+`
|
|
76
76
|
`),process.stdout.write(w(" Client Secret: ")+e+`
|
|
77
77
|
`),process.stdout.write(w(" Storage: ")+`ANTHROPIC_AUTH_TOKEN (settings.json)
|
|
78
78
|
|
|
79
|
-
`),0}var
|
|
80
|
-
`,{encoding:"utf8",mode:384});}catch{}return t}function
|
|
79
|
+
`),0}var so,zt=m(()=>{"use strict";we();ln();Bt();N();Xt();v();it();Ht();so=/[\x00-\x08\x0B-\x1F\x7F]|\x1b\[[0-9;]*[a-zA-Z]/g;});var lr={};W(lr,{normalizeCustomUrl:()=>fn,runInit:()=>mo,validateCustomUrl:()=>cr});function uo(){try{let t=g__namespace.readFileSync(k(),"utf8"),e=JSON.parse(t);return !!(e.env&&e.env[p.ANTHROPIC_AUTH_TOKEN])}catch{return false}}function po(){let t=Wt();if(!t)return null;H({FLOW_BASE_URL:t});try{let e=ge(),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 fn(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 cr(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.
|
|
81
81
|
Received: ${t}
|
|
82
82
|
Expected: https://tenant.example.com`);if(o.search)throw new Error(`Custom URL must not contain query parameters.
|
|
83
83
|
Received: ${t}
|
|
84
84
|
Expected: https://tenant.example.com`);if(o.hash)throw new Error(`Custom URL must not contain a fragment.
|
|
85
85
|
Received: ${t}
|
|
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=
|
|
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=fn(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 dn(){for(let t=1;t<=3;t++)try{let e=await ue(" Enter your Flow domain (e.g., tenant.ciandt.com)");return cr(e)}catch(e){if(process.stderr.write(_(` \u2717 ${e.message}
|
|
87
87
|
|
|
88
88
|
`)),t===3)throw process.stderr.write(R(` Too many invalid attempts.
|
|
89
89
|
|
|
90
|
-
`)),new Error("Too many invalid URL attempts")}throw new Error("Too many invalid URL attempts")}async function
|
|
90
|
+
`)),new Error("Too many invalid URL attempts")}throw new Error("Too many invalid URL attempts")}async function fo(t,e){let r=ft(),n=r??"(could not be derived)";if(!t||!at()){process.stdout.write(w(` e-mail: ${n}
|
|
91
91
|
`)+(r?w(` To use a different email, set FLOW_USER_EMAIL in ~/.claude/settings.json env block.
|
|
92
92
|
`):_(` Could not derive your email. Set FLOW_USER_EMAIL before running hooks.
|
|
93
93
|
`)));return}if(!r){process.stdout.write(_(`
|
|
94
94
|
\u26A0 Could not derive email from OS username.
|
|
95
|
-
`));let s=await
|
|
95
|
+
`));let s=await ue(" 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}
|
|
96
96
|
|
|
97
|
-
`));return}if(e)if(await
|
|
97
|
+
`));return}if(e)if(await le(" Is your corporate email domain @ciandt.com?",true))process.stdout.write(L(` \u2713 Email: ${b(n)}
|
|
98
98
|
|
|
99
|
-
`));else {let o=await
|
|
99
|
+
`));else {let o=await ue(" 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}
|
|
100
100
|
|
|
101
101
|
`));}else process.stdout.write(L(` \u2713 Email: ${b(n)}
|
|
102
102
|
|
|
103
|
-
`));}function
|
|
103
|
+
`));}function pn(){try{let t=g__namespace.readFileSync(k(),"utf8"),r=JSON.parse(t).env?.FLOW_BASE_URL;return typeof r=="string"&&r.trim()?r.trim():null}catch{return null}}async function mo(t={}){let e=ut();if(e)return e;let r=t.url;if(!ye())return process.stderr.write(`
|
|
104
104
|
`+R(` \u2717 Claude Code is not installed or not found in PATH.
|
|
105
105
|
|
|
106
106
|
`)+` flow-ai-obs requires Claude Code to function.
|
|
@@ -112,30 +112,30 @@
|
|
|
112
112
|
`)+_(" on Windows too: ")+I(`npm install -g @ciandt-flow/flow-ai-obs
|
|
113
113
|
`)+_(` Running Claude (Windows) + flow-ai-obs (WSL) is not a supported configuration.
|
|
114
114
|
|
|
115
|
-
`));let n=
|
|
115
|
+
`));let n=po();if(n&&process.stdout.write(_(` \u26A0 Legacy config migrated.
|
|
116
116
|
`)+w(` Custom URL moved from ~/.config/flow-ai-obs/config.json
|
|
117
117
|
`)+w(` to FLOW_BASE_URL in ~/.claude/settings.json: ${n}
|
|
118
118
|
|
|
119
|
-
`)),!r&&!t.noInteractive&&at()){let d=
|
|
119
|
+
`)),!r&&!t.noInteractive&&at()){let d=pn();try{d?(process.stdout.write(`
|
|
120
120
|
Current base URL: ${b(d)}
|
|
121
|
-
`),await
|
|
122
|
-
`),await
|
|
123
|
-
`);}if(!r&&!t.noInteractive&&!at()){let d=
|
|
121
|
+
`),await le(" Keep this URL?",!0)||(r=await dn())):(process.stdout.write(`
|
|
122
|
+
`),await le(" Does your organization use a custom Flow URL?",!1)&&(r=await dn()));}catch{return 1}process.stdout.write(`
|
|
123
|
+
`);}if(!r&&!t.noInteractive&&!at()){let d=pn(),h=process.env.FLOW_BASE_URL,E=d??h??Dt,S=!!(d??h);process.stdout.write(_(` \u26A0 Non-interactive environment detected.
|
|
124
124
|
`)+w(` Using URL: ${E}
|
|
125
125
|
`)+(S?"":w(` Run with --custom-url to configure a custom domain.
|
|
126
126
|
`))+`
|
|
127
|
-
`);}await
|
|
127
|
+
`);}await fo(!t.noInteractive,!!(r??Wt()));let s=null,o=null;if(r){let d;try{d=cr(r,!0);}catch(Tt){return process.stderr.write(`
|
|
128
128
|
\u2717 Invalid --custom-url: ${Tt.message}
|
|
129
129
|
|
|
130
|
-
`),1}let h=Wt(),E
|
|
130
|
+
`),1}let h=Wt(),E=Fr(),S=`${d}/otel`,A=`${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:A},s=d,h&&h!==d?process.stdout.write(_(` \u26A0 Base URL updated.
|
|
131
131
|
`)+w(` Previous: ${h}
|
|
132
132
|
`)+w(` New: ${d}
|
|
133
133
|
|
|
134
134
|
`)):process.stdout.write(L(` \u2713 Base URL configured: ${d}
|
|
135
135
|
|
|
136
|
-
`));}if(!
|
|
136
|
+
`));}if(!uo())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.
|
|
137
137
|
|
|
138
|
-
`));let{runLogin:d}=await Promise.resolve().then(()=>(
|
|
138
|
+
`));let{runLogin:d}=await Promise.resolve().then(()=>(zt(),ar)),h=await d();if(h!==0)return h}let i,a;try{(({settingsPath:i,preserved:a}=en())),o&&H(o);}catch(d){return process.stderr.write(` \u2717 Failed to write settings: ${d.message}
|
|
139
139
|
`),1}process.stdout.write(`
|
|
140
140
|
`+b(" Native OTEL configured")+` (metrics & logs)
|
|
141
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+`
|
|
@@ -155,13 +155,13 @@
|
|
|
155
155
|
`));let u=s??Wt()??process.env.FLOW_BASE_URL??Dt;return process.stdout.write(w(" Base URL: ")+u+`
|
|
156
156
|
`),process.stdout.write(`
|
|
157
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
|
|
158
|
+
`)),process.stdout.write(w(" Run `flow-ai-obs setup` to configure a full environment from scratch.\n\n"))),0}var ur=m(()=>{"use strict";Xt();v();it();me();Ht();N();Je();sr();$e();});var hn={};W(hn,{runSetup:()=>To});function go(){try{return JSON.parse(g__namespace.readFileSync(k(),"utf8"))}catch{return {}}}function ho(t){return !!(t.env??{}).ANTHROPIC_BASE_URL}function Eo(t){let e=t.env??{};return Object.keys(V).every(r=>!!e[r])}function wo(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 So(t){return (await X(t)).trim().toLowerCase()==="y"}function Oe(t,e,r){process.stdout.write(`
|
|
159
159
|
${b(`[${t}/${e}]`)} ${r}
|
|
160
|
-
`);}function
|
|
161
|
-
`));}function
|
|
162
|
-
`));}function
|
|
160
|
+
`);}function J(t){process.stdout.write(L(` \u2713 ${t}
|
|
161
|
+
`));}function mn(t){process.stdout.write(_(` \u26A0 ${t}
|
|
162
|
+
`));}function Zt(t){process.stderr.write(R(` \u2717 ${t}
|
|
163
163
|
`));}function gt(t){process.stdout.write(w(` ${t}
|
|
164
|
-
`));}async function
|
|
164
|
+
`));}async function To(t={}){let e=ut();if(e)return e;let r=4;process.stdout.write(`
|
|
165
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
|
|
166
166
|
`),process.stdout.write(`\u2551 flow-ai-obs \u2014 setup \u2551
|
|
167
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
|
|
@@ -172,37 +172,37 @@ ${b(`[${t}/${e}]`)} ${r}
|
|
|
172
172
|
`)),process.stdout.write(w(` [3/4] AI Usage Enable native OTEL telemetry
|
|
173
173
|
`)),process.stdout.write(w(` [4/4] Langfuse Register trace capture hooks
|
|
174
174
|
`)),process.stdout.write(`
|
|
175
|
-
`);let n=
|
|
176
|
-
`)),1;let o=
|
|
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()),
|
|
178
|
-
`+L(" \u2713 Setup complete. Run `claude` to start.\n\n")),0}var
|
|
179
|
-
`),0}var
|
|
180
|
-
`);}function
|
|
181
|
-
`);}function
|
|
175
|
+
`);let n=go();if(Oe(1,r,"Checking Claude Code..."),ye()){let s=nr();J(s?`Already installed (${s}) \u2014 skipping.`:"Already installed \u2014 skipping.");}else {gt("Not found. Installing via npm...");let s=sn();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=nr();J(o?`Claude Code ${o} installed.`:"Claude Code installed.");}if(Oe(2,r,"Configuring proxy..."),ho(n)){let s=n.env.ANTHROPIC_BASE_URL;mn(`Proxy already configured (${s})`);let o=t.nonInteractive||!process.stdin.isTTY,i=false;if(!o)try{i=await So(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()),J("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()),J("Proxy configured."),gt(`Settings: ${k()}`);}catch(o){return Zt(`Could not write proxy config: ${o.message}`),1}}if(Oe(3,r,"Configuring AI Usage..."),t.url){let{runInit:s}=await Promise.resolve().then(()=>(ur(),lr)),o=await s({noInteractive:true,url:t.url,skipHint:true});if(o!==0)return o;J("AI Usage configured with custom URL.");}else if(Eo(n))J("Already configured \u2014 skipping.");else try{H(V),J("AI Usage configured."),gt(`Settings: ${k()}`);}catch(s){return Zt(`Could not write AI Usage config: ${s.message}`),1}if(Oe(4,r,"Configuring Langfuse..."),wo(n))J("Already configured \u2014 skipping.");else {let s,o;try{({settingsPath:s,preserved:o}=rn());}catch(i){return Zt(`Could not write hooks: ${i.message}`),1}J("Hooks registered (UserPromptSubmit, PreToolUse, PostToolUse, Stop)"),o.length>0&&(mn(`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 En=m(()=>{"use strict";v();it();Ht();zt();Xt();sr();});var wn={};W(wn,{runOtelHeaders:()=>yo});async function yo(){let t={},e=ft();e&&(t["x-flow-user"]=e);let r=Jt();return r&&(t["x-flow-api-key"]=r),process.stdout.write(JSON.stringify(t)+`
|
|
179
|
+
`),0}var Sn=m(()=>{"use strict";N();});var yn={};W(yn,{runCheck:()=>_o});function dr(t){return !t||t.length<=8?"****":t.slice(0,4)+"****...****"+t.slice(-4)}function Qt(t){process.stdout.write(` \u2713 ${t}
|
|
180
|
+
`);}function ve(t){process.stdout.write(` \u26A0 ${t}
|
|
181
|
+
`);}function Ae(t){process.stdout.write(` \u2717 ${t}
|
|
182
182
|
`);}function U(t){process.stdout.write(` ${t}
|
|
183
183
|
`);}function $(){process.stdout.write(`
|
|
184
|
-
`);}async function
|
|
184
|
+
`);}async function _o(){$(),process.stdout.write(` flow-claude-observability \u2014 configuration check
|
|
185
185
|
`),$(),process.stdout.write(` Auth
|
|
186
|
-
`);let t=()=>Pt(p.ANTHROPIC_AUTH_TOKEN)??process.env[p.ANTHROPIC_AUTH_TOKEN],e=B(t());if(!e){
|
|
187
|
-
`);}if(!await
|
|
188
|
-
`);}let r=await
|
|
189
|
-
`);let n={};try{let a=g__namespace.readFileSync(
|
|
190
|
-
`),process.env[p.FLOW_TELEMETRY]==="true"){
|
|
191
|
-
`),$(),0}var
|
|
192
|
-
`)[0].slice(0,e).trim()}function
|
|
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
|
|
186
|
+
`);let t=()=>Pt(p.ANTHROPIC_AUTH_TOKEN)??process.env[p.ANTHROPIC_AUTH_TOKEN],e=B(t());if(!e){ve("Not authenticated \u2014 starting setup..."),$();let a=await mt();if(a!==0)return a;if(e=B(t()),!e)return Ae("Authentication failed"),$(),1;$(),process.stdout.write(` Auth
|
|
187
|
+
`);}if(!await Ee()){ve("Session expired \u2014 re-authenticating..."),$();let a=await mt();if(a!==0)return a;$(),process.stdout.write(` Auth
|
|
188
|
+
`);}let r=await Kt()||e.clientId;Qt("Authenticated"),U(`Tenant: ${e.tenant}`),U(`User: ${r}`),$(),process.stdout.write(` Native OTEL
|
|
189
|
+
`);let n={};try{let a=g__namespace.readFileSync(k(),"utf8");n=JSON.parse(a).env||{};}catch{}let s=Object.keys(V).filter(a=>!n[a]);if(s.length===0?(Qt("All OTEL env vars present in settings.json"),U(`Endpoint: ${n.OTEL_EXPORTER_OTLP_ENDPOINT}`)):(ve(`${s.length} OTEL var(s) missing from settings.json \u2014 native metrics/logs disabled`),s.forEach(a=>Ae(`Missing: ${a}`)),U("Run: flow-ai-obs init (restores missing vars automatically)")),$(),process.stdout.write(` Tracing
|
|
190
|
+
`),process.env[p.FLOW_TELEMETRY]==="true"){Qt("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=>ve(`Missing: ${c}`));}else U("FLOW_TELEMETRY not set \u2014 direct mode inactive (gateway mode may still be active)");let i=await K();if(!i||i.length===0)return i&&i.authError?Ae("Token refresh failed \u2014 gateway mode could not activate"):(Ae("No active destinations \u2014 no traces will be sent"),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();Qt("Mode: gateway"),U(`Endpoint: ${a.endpoint}`),U(`Token: ${dr(c?.accessToken)}`);}else a.mode==="direct"&&(Qt("Mode: direct"),U(`Endpoint: ${a.endpoint}`),U(`PK: ${dr(process.env[p.LANGFUSE_PUBLIC_KEY])}`),U(`SK: ${dr(process.env[p.LANGFUSE_SECRET_KEY])}`));return $(),process.stdout.write(` All checks passed \u2014 observability is active.
|
|
191
|
+
`),$(),0}var _n=m(()=>{"use strict";we();N();Xt();v();zt();});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 ke(t,e=100){return String(t??"").split(`
|
|
192
|
+
`)[0].slice(0,e).trim()}function pr(){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 fr,ht,te=m(()=>{"use strict";fr=()=>crypto.randomBytes(16).toString("hex"),ht=()=>crypto.randomBytes(8).toString("hex");});function No(t,e){let r=Rt.resolve(t);if(!r.startsWith(e))throw new Error(`Path traversal detected: ${t}`);return r}function mr(t){if(!bo.test(t))throw new Error(`Invalid session ID: ${t}`);return No(Rt.join(dt.tmpdir(),`flow-obs-${t}.json`),Co)}function Nt(t){let e=mr(t);if(!g.existsSync(e))return null;try{return JSON.parse(g.readFileSync(e,"utf8"))}catch{return null}}function Ut(t,e){g.writeFileSync(mr(t),JSON.stringify(e),{encoding:"utf8",mode:384});}function gr(t){try{g.unlinkSync(mr(t));}catch{}}var bo,Co,ee=m(()=>{"use strict";bo=/^[0-9a-f-]{1,64}$/i,Co=Rt.normalize(dt.tmpdir())+Rt.sep;});function Ln(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 hr(t){if(!t||!g.existsSync(t))return null;try{let e=g.readFileSync(t,"utf8").trimEnd().split(`
|
|
194
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
195
|
|
|
196
|
-
`),inputTokens:n,outputTokens:s}}catch{}return null}var
|
|
197
|
-
`)[0].match(/^\/([a-z][a-z0-9-]*(?::[a-z][a-z0-9-]*)?)(?:\s.*)?$/i)?.[1]??null}function
|
|
198
|
-
`);return}let n=!!(await
|
|
199
|
-
`,{flag:"a",encoding:"utf8",mode:384}),l("sendTraces:dump",`request appendada em ${
|
|
196
|
+
`),inputTokens:n,outputTokens:s}}catch{}return null}var Er=m(()=>{"use strict";});function Pn(t){return t.replace(":","/")}function Le(t,e){if(!t)return null;let r=Pn(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 bn(t){return t.split(`
|
|
197
|
+
`)[0].match(/^\/([a-z][a-z0-9-]*(?::[a-z][a-z0-9-]*)?)(?:\s.*)?$/i)?.[1]??null}function Cn(t){return !!t.slashSkill||t.toolCalls.some(n=>n.tool==="Skill")?t.toolCalls.some(n=>n.tool==="Skill"&&!n.synthetic||Bo.has(n.tool))?"complete":"prerequisite_required":null}function Re(t,e){if(!t)return null;let r=Pn(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(xo.has(u.name)||Mo.has(u.name)||Do.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 xo,Do,Mo,Bo,Ie=m(()=>{"use strict";xo=new Set([".venv","__pycache__",".git","node_modules"]),Do=new Set([".pyc",".pyo"]),Mo=new Set(["SKILL.md",".DS_Store",".gitignore"]);Bo=new Set(["Read","Write","Edit","MultiEdit","Bash","Glob","Grep","TodoWrite","WebFetch","WebSearch","Agent","Task"]);});function Wo(t){try{let e=t.split(".")[1].replace(/-/g,"+").replace(/_/g,"/");return JSON.parse(Buffer.from(e,"base64").toString())}catch{return null}}function Vo(t,e,r,n){return new Promise(s=>{let o=new URL(t),i=o.protocol==="https:",a=(i?Es__default.default:Ns__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=Wo(o);if(!i)return;let a=i.tenant||r.tenant,c=JSON.stringify({action:t,booster:Ye().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(Ye().API_URL),d=await Vo(u,c,o,a);l("metrics.logEvent",`action=${t} status=${d}`);}catch(r){l("metrics.logEvent",`silenced error: ${r.message}`);}}var Pe=m(()=>{"use strict";v();Bt();N();M();});async function wr(t,e=false){if(e){process.stdout.write(JSON.stringify({decision:"block",reason:Yo})+`
|
|
198
|
+
`);return}let n=!!(await K()).authError,s=t.session_id||"unknown",o=t.prompt||"",i=t.cwd||"",a=Ln(t.transcript_path)||fr(),c=bn(o),u=c?Le(c,i):null,d=c?Re(c,i):null;Ut(s,{traceId:fr(),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 Yo,Nn=m(()=>{"use strict";te();ee();Er();Ie();Ct();M();v();N();Pe();Yo=`\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 Un(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 $n=m(()=>{"use strict";te();ee();Ct();M();v();});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 Fn(t,e){return {resourceSpans:[{resource:{attributes:t},scopeSpans:[{scope:Go,spans:Array.isArray(e)?e:[e]}]}]}}var Go,y,xn=m(()=>{"use strict";v();Go={name:We.SCOPE_NAME,version:We.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 Mn(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(Dn,o+`
|
|
199
|
+
`,{flag:"a",encoding:"utf8",mode:384}),l("sendTraces:dump",`request appendada em ${Dn}`);}catch(i){l("sendTraces:dump",`falha ao salvar: ${i.message}`);}}function Zo(t){let e=new URL(t),r=new URL(kt().GATEWAY_HEALTH);return r.hostname=e.hostname,r.port=e.port,r.protocol=e.protocol,r}function Bn(t,e){return new Promise((r,n)=>{let s=t._isSSL?Es__default.default:Ns__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 Hn(t){let e;try{e=Zo(t);}catch{return false}let r=e.protocol==="https:";try{let n=await Bn({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 be(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":Jt()??""};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 Bn({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}`),Mn(e,o,r,i.statusCode,i.body),i.statusCode}catch(i){return l("sendTraces:error",i.message),Mn(e,o,r,0,i.message),0}}var Dn,jn=m(()=>{"use strict";v();M();N();Dn=Rt.join(dt.tmpdir(),"flow-obs-requests.ndjson");});function Qo(){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 ti(){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 Vn(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 Tr(){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 re(t){try{let e=ti(),r=Tr();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(Vn(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 Yn(t){let e=Tr(),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 Gn(t){try{g__namespace.default.unlinkSync(Vn(t)),l("buffer",`deleted fileId=${t}`);}catch{}}function Kn(){let t=Date.now()-Qo();for(let e of Tr())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";v();M();});async function ei(t){Kn();let e=Yn(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 be(r.payload,t.endpoint);n>=200&&n<300?(Gn(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 qn(t){let e=await K();if(!e.length)return e.authError&&(l("postToLangfuse","auth refresh failed \u2014 buffering trace"),re(t)),0;let r=await Promise.all(e.map(async o=>{if(o.mode!=="gateway")return {creds:o,healthy:true};let i=await Hn(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 ei(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"),re(t),0;let c=await be(t,o.endpoint);return (c===0||c>=500)&&(l("postToLangfuse",`gateway send failed (status ${c}) \u2014 buffering trace`),re(t)),c}let a=await be(t,o.endpoint);return (a===0||a>=500)&&(l("postToLangfuse",`direct endpoint unavailable (status ${a}) \u2014 buffering trace`),re(t)),a}))).find(o=>o!==0)??0}var Xn=m(()=>{"use strict";N();M();jn();Jn();v();});var yr=m(()=>{"use strict";xn();Xn();});function et(t){if(t==null)return "";let e=typeof t=="string"?t:JSON.stringify(t);return oi.reduce((r,{re:n,replace:s})=>r.replace(n,s),e)}var F,ri,ni,si,zn,oi,_r=m(()=>{"use strict";F="[REDACTED]",ri="[REDACTED-EMAIL]",ni="[REDACTED-CPF]",si="[REDACTED-CNPJ]",zn="[REDACTED-PHONE]",oi=[{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
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:()=>
|
|
202
|
-
`)),
|
|
203
|
-
`),process.stdout.write(JSON.stringify(e));}}var
|
|
204
|
-
`),process.exit(0);});});var
|
|
205
|
-
`),process.exit(0);}else if(x==="--help"||x==="-h"){let{bold:t,cyan:e,dim:r}=(it(),P(
|
|
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:()=>ri},{re:/\b\d{3}\.\d{3}\.\d{3}-\d{2}\b/g,replace:()=>ni},{re:/\b\d{2}\.\d{3}\.\d{3}\/\d{4}-\d{2}\b/g,replace:()=>si},{re:/\(\d{2}\)\s?\d{4,5}[-\s]?\d{4}/g,replace:()=>zn},{re:/\+55[\s-]?\d{2}[\s-]?\d{4,5}[-\s]?\d{4}/g,replace:()=>zn}];});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 ae=typeof n=="object"&&n!==null?n.skill||n.name||n.skillName||n.commandName||String(Object.values(n)[0]??""):String(n);S=ae?String(ae).trim():null;let st=S?Le(S,i.cwd):null;st&&(E=st,i.skillContent||(i.skillContent=st),i.skillArtifacts||(i.skillArtifacts=Re(S,i.cwd))),S&&!i.slashSkill&&(i.slashSkill=S),l("PostToolUse","Skill tool detected",`skillName=${S}`,`contentFound=${!!st}`);}let A=et(G(o,Y.TOOL_OUTPUT)),O=/\b(error|exception|failed|failure|traceback|errno)\b/i.test(A.slice(0,500)),St=O?"ERROR":"DEFAULT",nt=ht(),Tt=Math.round(Number(BigInt(a)-BigInt(d))/1e6),oe={Agent:"AGENT",Task:"AGENT"}[r]??"TOOL",ie=r==="Skill"&&S?S:ke(h,60);i.toolCalls.push({tool:r,brief:ie,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,oe),f(y.OBS_LEVEL,St),f(y.OBS_INPUT,et(E)),f(y.OBS_OUTPUT,A),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 Qn=m(()=>{"use strict";te();ee();yr();Ct();Ie();M();v();_r();Pe();});function es(t,e,r){let n=Object.keys(ts).find(i=>(t??"").toLowerCase().includes(i));if(!n)return;let s=ts[n],o=(e*s.input+r*s.output)/1e6;return Math.round(o*1e6)/1e6}var ts,rs=m(()=>{"use strict";ts={"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 ns(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=hr(c);if(c&&(i.some(T=>T.tool==="Skill"&&!T.synthetic)||!!n.slashSkill)&&!u?.text){await new Promise(ot=>setTimeout(ot,500));let T=hr(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
|
+
`)),A=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"}),gr(e),j(t);return}let se=nt?"skill":"agent",oe=Math.round(Number(BigInt(s)-BigInt(n.startNs))/1e6),ie=es(n.model,A,O),yt=Cn(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}})(),ae=JSON.stringify({trace_type:se,...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:oe,...A&&{tokens_input:A},...O&&{tokens_output:O},cost_usd:ie,...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)),is=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,ae),f(y.SESSION_ID,n.sessionId),f(y.USER_ID,o.user),f(y.OBS_TYPE,"GENERATION"),f(y.MODEL,n.model),A?f(y.INPUT_TOKENS,A):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",se),{key:y.TRACE_TAGS,value:{arrayValue:{values:[{stringValue:se}]}}}),as={traceId:n.traceId,spanId:n.spanId,name:n.traceName,kind:1,startTimeUnixNano:n.startNs,endTimeUnixNano:s,attributes:is,status:{code:E>0?2:1}},cs=wt(f("service.name",process.env.LANGFUSE_PROJECT_NAME||"claude-code"),f("deployment.environment",process.env.LANGFUSE_ENVIRONMENT||"default")),Or=[...a,as];l("Stop",`sid=${e}`,`totalTools=${h}`,`errorTools=${E}`,`spans=${Or.length}`,`inputTokens=${A}`,`outputTokens=${O}`,`traceOutput="${ke(S,80)}"`);let ls=await qn(Fn(cs,Or));l("Stop",`POST status=${ls}`,`traceId=${n.traceId}`),Et("TRACE_SENT",{latencyMs:oe,totalTools:h,errorTools:E,inputTokens:A,outputTokens:O,costUsd:ie}),gr(e),j(t);}var ss=m(()=>{"use strict";te();ee();yr();N();rs();Er();Ct();M();Ie();_r();v();Pe();});async function ii(){let t=process.argv[2];if(t==="UserPromptSubmit"){let r=await pr(),n;try{n=await K();}catch{process.stdout.write(JSON.stringify(r));return}n.authError?await wr(r,true):n.length>0?await wr(r):process.stdout.write(JSON.stringify(r));return}if(!await Qr()){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 Un(e);break;case "PostToolUse":await Zn(e);break;case "Stop":await ns(e);break;default:process.stderr.write(`[flow-obs] unknown event: ${t}
|
|
203
|
+
`),process.stdout.write(JSON.stringify(e));}}var os=m(()=>{"use strict";N();Ct();Nn();$n();Qn();ss();ii().catch(t=>{process.stderr.write(`[flow-obs] fatal: ${t.message}
|
|
204
|
+
`),process.exit(0);});});var ci=new Set(["UserPromptSubmit","PreToolUse","PostToolUse","Stop"]),[,,x,ne]=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}=ce();process.stdout.write(t+`
|
|
205
|
+
`),process.exit(0);}else if(x==="--help"||x==="-h"){let{bold:t,cyan:e,dim:r}=(it(),P(Ne)),{version:n}=ce();process.stdout.write(`
|
|
206
206
|
`+t(" flow-ai-obs")+r(" v"+n)+`
|
|
207
207
|
|
|
208
208
|
`),process.stdout.write(e(" init")+r(` Auth (if needed) + hooks + native OTEL
|
|
@@ -223,12 +223,12 @@ ${r}`},{re:/\b(AKIA[0-9A-Z]{16})\b/g,replace:()=>`AKIA${F}`},{re:/(aws_secret_ac
|
|
|
223
223
|
`)),process.stdout.write(r(` (Hook events: UserPromptSubmit | PreToolUse | PostToolUse | Stop)
|
|
224
224
|
|
|
225
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(
|
|
227
|
-
`),process.exit(1);});else if(x==="setup")(async()=>{await(
|
|
228
|
-
`),process.exit(1);});else if(x==="auth")(async()=>{let{runLogin:t,runLogout:e,runStatus:r}=(
|
|
226
|
+
`),await(At(),P(vt)).checkForUpdateInteractive();let{runInit:t}=(ur(),P(lr)),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(At(),P(vt)).checkForUpdateInteractive();let{runSetup:t}=(En(),P(hn)),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}=(zt(),P(ar)),n=0;if(ne==="login"||!ne){await(At(),P(vt)).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(ne==="logout"){let s=process.argv.includes("--force");n=await e(s);}else ne==="status"?(await(At(),P(vt)).checkForUpdateInteractive(),n=await r()):(process.stderr.write(`Unknown auth subcommand: ${ne}
|
|
229
229
|
`),process.stderr.write(`Usage: flow-ai-obs auth [login|logout|status]
|
|
230
|
-
`),n=1);process.exit(n);})();else if(x==="otel-headers"){let{runOtelHeaders:t}=(
|
|
231
|
-
`),process.exit(1);});else if(
|
|
230
|
+
`),n=1);process.exit(n);})();else if(x==="otel-headers"){let{runOtelHeaders:t}=(Sn(),P(wn));t().then(e=>process.exit(e)).catch(()=>process.exit(1));}else if(x==="check")(async()=>{await(At(),P(vt)).checkForUpdateInteractive();let{runCheck:t}=(_n(),P(yn));process.exit(await t());})().catch(t=>{process.stderr.write(`Unexpected error: ${t.message}
|
|
231
|
+
`),process.exit(1);});else if(ci.has(x))os();else {let{bold:t,cyan:e,dim:r}=(it(),P(Ne));process.stdout.write(`
|
|
232
232
|
`+t(" flow-ai-obs")+`
|
|
233
233
|
|
|
234
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'),I=require('fs'),
|
|
1
|
+
'use strict';var child_process=require('child_process'),util=require('util'),I=require('fs'),_e=require('os'),x=require('path'),qe=require('https'),Xe=require('http'),crypto=require('crypto');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var I__default=/*#__PURE__*/_interopDefault(I);var _e__default=/*#__PURE__*/_interopDefault(_e);var x__default=/*#__PURE__*/_interopDefault(x);var qe__default=/*#__PURE__*/_interopDefault(qe);var Xe__default=/*#__PURE__*/_interopDefault(Xe);var be=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)be(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",ve="https://dev.flow.ciandt.com";function D(){let t=process.env.FLOW_BASE_URL;return t&&t.trim()?t.trim():ve}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 Et={credentials:"credentials","token-cache":"tokenCache"};function G(){let t=_e__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 St(){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=St(),i=Et[r]??r,s=n[i];return s?typeof s=="string"?s:JSON.stringify(s):null}async setSecret(e,r,n){let i=St(),s=Et[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=St(),i=Et[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 Ye()??new ot}async function Ye(){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,Kt=rt.ACCOUNT_TOKEN,Ot=null;function jt(){return Ot||(Ot=Gt()),Ot}async function wt(t){await(await jt()).setSecret(Jt,Kt,JSON.stringify({accessToken:t.accessToken,expiresAt:t.expiresAt,lastAuthCheckAt:t.lastAuthCheckAt}));}async function kt(){let e=await(await jt()).getSecret(Jt,Kt);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(_e.tmpdir(),Ft);function a(...t){if(process.env[_.FLOW_OBS_DEBUG]!=="1")return;let e=`[${new Date().toISOString()}] ${t.join(" ")}
|
|
2
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";}},
|
|
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
|
|
3
|
+
`);}}var b=class extends Error{constructor(e){super(e),this.name="AuthError";}},ze=/^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$|^[a-z0-9]$/;function Ze(t){if(!ze.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 Qe(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 K(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?qe__default.default:Xe__default.default).request(o,p=>{let E=[];p.on("data",S=>E.push(S)),p.on("end",()=>{let S=E.join("");if((p.statusCode??0)>=400)return r(Qe(p.statusCode??0,S));let m;try{m=JSON.parse(S);}catch{return r(new Error("Invalid response from auth engine"))}let g=m.expires_at??new Date(Date.now()+(m.expires_in??3600)*1e3).toISOString();e({accessToken:m.access_token??"",expiresAt:g});});});l.on("error",p=>r(new Error(`Network error: ${p.message}`))),l.write(n),l.end();})}var er=[/^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 rr(t){return er.some(e=>e.test(t))}function nr(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&&rr(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 sr(){return new Date().toISOString().slice(0,10)}async function or(t){let e=sr(),r=await kt();if(r?.lastAuthCheckAt!==e){a("getOrRefreshToken",`daily auth check (last: ${r?.lastAuthCheckAt??"never"})`);try{let s=await K(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 K(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 ir(t,e){let r=e&&e.accessToken?e.accessToken:"";return {endpoint:t.replace(/\/$/,"")+"/flow-langfuse-gateway/v1/traces",authHeader:`Bearer ${r}`}}function ar(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",...ar(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 or(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 E={user:nr(l)??r.clientId,tenant:n,team:"",project:"",model:e},S=process.env[_.FLOW_TELEMETRY_GATEWAY]??D();return t.push({mode:"gateway",...ir(it(S),{accessToken:l}),...E}),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=_e__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 Qt(){return process.env.OTEL_EXPORTER_OTLP_HEADERS??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 _r=/^[0-9a-f-]{1,64}$/i,Er=x.normalize(_e.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(!_r.test(t))throw new Error(`Invalid session ID: ${t}`);return Sr(x.join(_e.tmpdir(),`flow-obs-${t}.json`),Er)}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 se(t){if(!t||!I.existsSync(t))return null;try{let e=I.readFileSync(t,"utf8").trimEnd().split(`
|
|
5
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(
|
|
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(E=>E.type==="text").map(E=>E.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:i}}catch{}return null}var
|
|
9
|
-
`)[0].match(/^\/([a-z][a-z0-9-]*(?::[a-z][a-z0-9-]*)?)(?:\s.*)?$/i)?.[1]??null}var
|
|
10
|
-
`);return}let n=!!(await v()).authError,i=t.session_id||"unknown",s=t.prompt||"",o=t.cwd||"",u=
|
|
11
|
-
`,{flag:"a",encoding:"utf8",mode:384}),a("sendTraces:dump",`request appendada em ${
|
|
8
|
+
`),inputTokens:n,outputTokens:i}}catch{}return null}var Ar=new Set([".venv","__pycache__",".git","node_modules"]),Or=new Set([".pyc",".pyo"]),wr=new Set(["SKILL.md",".DS_Store",".gitignore"]);function ae(t){return t.replace(":","/")}function lt(t,e){if(!t)return null;let r=ae(t),n=[x.join(_e.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 ce(t){return t.split(`
|
|
9
|
+
`)[0].match(/^\/([a-z][a-z0-9-]*(?::[a-z][a-z0-9-]*)?)(?:\s.*)?$/i)?.[1]??null}var kr=new Set(["Read","Write","Edit","MultiEdit","Bash","Glob","Grep","TodoWrite","WebFetch","WebSearch","Agent","Task"]);function le(t){return !!t.slashSkill||t.toolCalls.some(n=>n.tool==="Skill")?t.toolCalls.some(n=>n.tool==="Skill"&&!n.synthetic||kr.has(n.tool))?"complete":"prerequisite_required":null}function ut(t,e){if(!t)return null;let r=ae(t),n=[x.join(_e.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(Ar.has(p.name)||wr.has(p.name)||Or.has(x.extname(p.name)))continue;let E=l?`${l}/${p.name}`:p.name;p.isDirectory()?o(x.join(u,p.name),E):s.push(E);}}return o(i,""),s.length>0?s:null}function Rr(t){try{let e=t.split(".")[1].replace(/-/g,"+").replace(/_/g,"/");return JSON.parse(Buffer.from(e,"base64").toString())}catch{return null}}function Nr(t,e,r,n){return new Promise(i=>{let s=new URL(t),o=s.protocol==="https:",u=(o?qe__default.default:Xe__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((S,m)=>{n=setTimeout(()=>m(new Error("getToken timeout")),4e3),n.unref();}),{accessToken:s}=await Promise.race([K(r),i]);clearTimeout(n);let o=Rr(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),E=await Nr(p,l,s,u);a("metrics.logEvent",`action=${t} status=${E}`);}catch(r){a("metrics.logEvent",`silenced error: ${r.message}`);}}var Pr=`\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:Pr})+`
|
|
10
|
+
`);return}let n=!!(await v()).authError,i=t.session_id||"unknown",s=t.prompt||"",o=t.cwd||"",u=se(t.transcript_path)||Rt(),l=ce(s),p=l?lt(l,o):null,E=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:E}),C("SESSION_STARTED",{traceType:l?"skill":"prompt",slashSkill:l,clientIdExpired:n}),a("UserPromptSubmit",`sid=${i}`,`traceName=${u}`,`slashSkill=${l}`),O(t);}async function ue(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 br={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 pe(t,e){return {resourceSpans:[{resource:{attributes:t},scopeSpans:[{scope:br,spans:Array.isArray(e)?e:[e]}]}]}}var de=x.join(_e.tmpdir(),"flow-obs-requests.ndjson");function fe(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(de,s+`
|
|
11
|
+
`,{flag:"a",encoding:"utf8",mode:384}),a("sendTraces:dump",`request appendada em ${de}`);}catch(o){a("sendTraces:dump",`falha ao salvar: ${o.message}`);}}function Dr(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 me(t,e){return new Promise((r,n)=>{let i=t._isSSL?qe__default.default:Xe__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 ge(t){let e;try{e=Dr(t);}catch{return false}let r=e.protocol==="https:";try{let n=await me({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":Qt()??""};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 me({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}`),fe(e,s,r,o.statusCode,o.body),o.statusCode}catch(o){return a("sendTraces:error",o.message),fe(e,s,r,0,o.message),0}}function xr(){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 Mr(){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 Ee(t){if(/[/\\]/.test(t))throw new Error(`Invalid buffer fileId: ${t}`);return x__default.default.join(_e__default.default.tmpdir(),`${A.FILE_PREFIX}${t}.json`)}function Ct(){let t=_e__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 j(t){try{let e=Mr(),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(Ee(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 Te(t){try{I__default.default.unlinkSync(Ee(t)),a("buffer",`deleted fileId=${t}`);}catch{}}function he(){let t=Date.now()-xr();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 Br(t){he();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?(Te(r.fileId),a("replayBufferedTraces",`replayed fileId=${r.fileId} status=${n}`)):a("replayBufferedTraces",`replay failed fileId=${r.fileId} status=${n}`);}catch(n){a("replayBufferedTraces",`replay error fileId=${r.fileId}: ${n.message}`);}})));}async function ye(t){let e=await v();if(!e.length)return e.authError&&(a("postToLangfuse","auth refresh failed \u2014 buffering trace"),j(t)),0;let r=await Promise.all(e.map(async s=>{if(s.mode!=="gateway")return {creds:s,healthy:true};let o=await ge(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 Br(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"),j(t),0;let l=await pt(t,s.endpoint);return (l===0||l>=500)&&(a("postToLangfuse",`gateway send failed (status ${l}) \u2014 buffering trace`),j(t)),l}let u=await pt(t,s.endpoint);return (u===0||u>=500)&&(a("postToLangfuse",`direct endpoint unavailable (status ${u}) \u2014 buffering trace`),j(t)),u}))).find(s=>s!==0)??0}var y="[REDACTED]",Vr="[REDACTED-EMAIL]",Wr="[REDACTED-CPF]",Hr="[REDACTED-CNPJ]",Ae="[REDACTED-PHONE]",Yr=[{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
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:()=>
|
|
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=
|
|
15
|
-
`),process.stdout.write(JSON.stringify(e));}}
|
|
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:()=>Vr},{re:/\b\d{3}\.\d{3}\.\d{3}-\d{2}\b/g,replace:()=>Wr},{re:/\b\d{2}\.\d{3}\.\d{3}\/\d{4}-\d{2}\b/g,replace:()=>Hr},{re:/\(\d{2}\)\s?\d{4,5}[-\s]?\d{4}/g,replace:()=>Ae},{re:/\+55[\s-]?\d{2}[\s-]?\d{4,5}[-\s]?\d{4}/g,replace:()=>Ae}];function R(t){if(t==null)return "";let e=typeof t=="string"?t:JSON.stringify(t);return Yr.reduce((r,{re:n,replace:i})=>r.replace(n,i),e)}async function Oe(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,E=p?l.startNs:String(BigInt(u)-200000000n),S=p?l.inputStr:k(n,w.TOOL_INPUT),m=S,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(E))/1e6),Z={Agent:"AGENT",Task:"AGENT"}[r]??"TOOL",Q=r==="Skill"&&g?g:ct(S,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:E,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 we={"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 ke(t,e,r){let n=Object.keys(we).find(o=>(t??"").toLowerCase().includes(o));if(!n)return;let i=we[n],s=(e*i.input+r*i.output)/1e6;return Math.round(s*1e6)/1e6}async function Le(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 S=o.length,m=o.filter(d=>d.error).length,g=R(p?.text?k(p.text,w.TRACE_OUTPUT):S===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=ke(n.model,T,h),F=le(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:S,errorCount:m,stopReason:r,sessionId:n.sessionId,tools:q.length?q:void 0}),N=R(k(n.prompt,w.TRACE_INPUT)),Ie=$(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(S)),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}]}}}),Re={traceId:n.traceId,spanId:n.spanId,name:n.traceName,kind:1,startTimeUnixNano:n.startNs,endTimeUnixNano:i,attributes:Ie,status:{code:m>0?2:1}},Ne=$(c("service.name",process.env.LANGFUSE_PROJECT_NAME||"claude-code"),c("deployment.environment",process.env.LANGFUSE_ENVIRONMENT||"default")),$t=[...u,Re];a("Stop",`sid=${e}`,`totalTools=${S}`,`errorTools=${m}`,`spans=${$t.length}`,`inputTokens=${T}`,`outputTokens=${h}`,`traceOutput="${ct(g,80)}"`);let Pe=await ye(pe(Ne,$t));a("Stop",`POST status=${Pe}`,`traceId=${n.traceId}`),C("TRACE_SENT",{latencyMs:Z,totalTools:S,errorTools:m,inputTokens:T,outputTokens:h,costUsd:Q}),Pt(e),O(t);}async function Gr(){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 ue(e);break;case "PostToolUse":await Oe(e);break;case "Stop":await Le(e);break;default:process.stderr.write(`[flow-obs] unknown event: ${t}
|
|
15
|
+
`),process.stdout.write(JSON.stringify(e));}}Gr().catch(t=>{process.stderr.write(`[flow-obs] fatal: ${t.message}
|
|
16
16
|
`),process.exit(0);});
|
package/dist/setup.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
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)+`
|
|
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 Se=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)Se(e,r,{get:t[r],enumerable:true});};var K={};L(K,{MacOsKeyVaultProvider:()=>b});var N,b,X=A(()=>{"use strict";N=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 N("security",["find-generic-password","-w","-a",r,"-s",t]);return n.trim()||null}catch{return null}}async setSecret(t,r,n){await N("security",["add-generic-password","-U","-a",r,"-s",t,"-w",n]);}async deleteSecret(t,r){try{return await N("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 _("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 me=Te((ur,Ke)=>{Ke.exports={name:"@ciandt-flow/flow-ai-obs",version:"0.7.0-beta.555",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(),S={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 C(){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=C(),s=I[r]??r,o=n[s];return o?typeof o=="string"?o:JSON.stringify(o):null}async setSecret(t,r,n){let s=C(),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=C(),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=S.SERVICE,$e=S.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
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
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.
|