@ciandt-flow/flow-ai-obs 0.7.0-beta.555 → 0.7.0-beta.582
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 +117 -114
- package/dist/index.js +14 -14
- package/dist/setup.js +5 -5
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,107 +1,107 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
'use strict';var Ue=require('readline/promises'),
|
|
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'),ws=require('https'),E=require('fs'),dt=require('os'),It=require('path'),child_process=require('child_process'),Us=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 ws__default=/*#__PURE__*/_interopDefault(ws);var E__namespace=/*#__PURE__*/_interopNamespace(E);var dt__namespace=/*#__PURE__*/_interopNamespace(dt);var It__namespace=/*#__PURE__*/_interopNamespace(It);var Us__default=/*#__PURE__*/_interopDefault(Us);var Ce=Object.defineProperty;var ds=Object.getOwnPropertyDescriptor;var ps=Object.getOwnPropertyNames;var fs=Object.prototype.hasOwnProperty;var Dt=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,r)=>(typeof require<"u"?require:e)[r]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var g=(t,e,r)=>()=>{if(r)throw r[0];try{return t&&(e=t(t=0)),e}catch(n){throw r=[n],n}};var ms=(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});},gs=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of ps(e))!fs.call(t,s)&&s!==r&&Ce(t,s,{get:()=>e[s],enumerable:!(n=ds(e,s))||n.enumerable});return t};var P=t=>gs(Ce({},"__esModule",{value:true}),t);var ae=ms((di,hs)=>{hs.exports={name:"@ciandt-flow/flow-ai-obs",version:"0.7.0-beta.582",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:()=>C,cyan:()=>I,dim:()=>w,green:()=>R,red:()=>L,yellow:()=>_});function yt(t,e){return Es?r=>`\x1B[${t}m${r}\x1B[${e}m`:r=>r}var Es,R,L,_,I,C,w,it=g(()=>{"use strict";Es=!process.env.NO_COLOR&&process.stdout.isTTY;R=yt("32","39"),L=yt("31","39"),_=yt("33","39"),I=yt("36","39"),C=yt("1","22"),w=yt("2","22");});function at(){return process.stdout.isTTY===true&&process.stdin.isTTY===true&&!process.argv.includes("--no-interactive")}async function ce(t,e){let r=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 le(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=g(()=>{"use strict";});var Ot={};W(Ot,{checkForUpdate:()=>ks,checkForUpdateInteractive:()=>vs,fetchLatestVersionAsync:()=>vr,isNewer:()=>_t,primeUpdateCache:()=>Rs});function N(){return Fe||(Fe=ae()),Fe}function _t(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(E__namespace.default.readFileSync(kr,"utf8"));return typeof t.latestVersion!="string"||Date.now()-t.checkedAt>=ys?null:t}catch{return null}}function Be(t,e,r=Date.now()){try{E__namespace.default.writeFileSync(kr,JSON.stringify({latestVersion:t,updatePriority:e??null,checkedAt:r}),{mode:384});}catch{}}function He(t){let e=N().name,r=ws__default.default.get(`https://registry.npmjs.org/${encodeURIComponent(e)}/latest`,{timeout:_s},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=N().name,n=` Update available: ${N().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 De(t){let e=
|
|
9
|
+
`);}function De(t){let e=N().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 Os(t,e=1e4){let r=Dt("readline"),n=N().name,o=` Update available: ${N().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}),
|
|
19
|
-
`),d(O));}let
|
|
18
|
+
`),new Promise(d=>{let h=r.createInterface({input:process.stdin,output:void 0,terminal:false}),f=false;function S(O){f||(f=true,clearTimeout(k),h.close(),process.stderr.write(`
|
|
19
|
+
`),d(O));}let k=setTimeout(()=>S(false),e);h.once("line",O=>S(O.trim().toLowerCase()==="y")),h.once("close",()=>S(false));})}async function As(t){let e=N().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{
|
|
28
|
-
`);}}var
|
|
29
|
-
`+
|
|
26
|
+
`),r();});})}function vr(){return new Promise(t=>{He((e,r)=>t(e||!r?null:r));})}function ks(){try{let t=Me();if(t){_t(N().version,t.latestVersion)&&(t.updatePriority==="auto"?De(t.latestVersion):xe(t.latestVersion));return}setImmediate(()=>{He((e,r)=>{e||!r||(Be(r.version,r.updatePriority),_t(N().version,r.version)&&(r.updatePriority==="auto"?De(r.version):xe(r.version)));});});}catch{}}async function vs(t={}){try{let e=Me();if(e){if(!_t(N().version,e.latestVersion))return}else {let n=await vr();if(!n||(Be(n.version,n.updatePriority),!_t(N().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 Os(e.latestVersion,t.timeoutMs)&&await As(e.latestVersion);}catch{}}function Rs(){try{if(Me())return;setImmediate(()=>{He((t,e)=>{t||!e||_t(N().version,e.version)&&Be(e.version,e.updatePriority,0);});});}catch{}}var Fe,kr,ys,_s,At=g(()=>{"use strict";$e();kr=It__namespace.default.join(dt__namespace.default.tmpdir(),"flow-obs-update-cache.json"),ys=1440*60*1e3,_s=3e3;});function ct(){let t=process.env.FLOW_BASE_URL;return t&&t.trim()?t.trim():Mt}function kt(){let t=ct();return {AUTH_ENGINE:process.env.FLOW_AUTH_ENGINE_URL||`${t}/auth-engine-api/v2/api-key/token`,GATEWAY_TRACES:process.env.FLOW_GATEWAY_TRACES_URL||`${t}/flow-langfuse-gateway/v1/traces`,GATEWAY_HEALTH:process.env.FLOW_GATEWAY_HEALTH_URL||`${t}/flow-langfuse-gateway/v1/health`,OTEL_ENDPOINT:process.env.FLOW_OTEL_ENDPOINT_URL||`${t}/otel`}}function Bt(){let t=ct();return {ANTHROPIC_BASE_URL:process.env.FLOW_LLM_PROXY_URL??`${t}/flow-llm-proxy/`,ANTHROPIC_MODEL:process.env.FLOW_LLM_PROXY_MODEL??"anthropic.claude-4-6-sonnet",ANTHROPIC_SMALL_FAST_MODEL:process.env.FLOW_LLM_PROXY_SMALL_MODEL??"anthropic.claude-4-6-sonnet",CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS:"1"}}function Ve(){let t=ct();return {API_URL:process.env.FLOW_METRICS_URL||`${t}/metrics-collector-api/log-event`,BOOSTER:"flow-ai-obs"}}var Mt,Ls,ue,de,pe,je,V,p,Rr,We,M,Lr,Y,A=g(()=>{"use strict";Mt="https://flow.ciandt.com";Ls=kt(),ue={SERVICE:"flow-plugins-cli",ACCOUNT_CREDS:"credentials",ACCOUNT_TOKEN:"token-cache"},de="FLOW-nodejs",pe="config.json",je={SCOPE_NAME:"flow-ai-obs",SCOPE_VERSION:"0.1.0"};V={CLAUDE_CODE_ENABLE_TELEMETRY:"1",OTEL_EXPORTER_OTLP_ENDPOINT:Ls.OTEL_ENDPOINT,OTEL_EXPORTER_OTLP_PROTOCOL:"http/json",OTEL_TRACES_EXPORTER:"otlp",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},We={UserPromptSubmit:5,PreToolUse:3,PostToolUse:10,Stop:15},M={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},Lr="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{E.writeFileSync(Cs,e,{flag:"a"});}catch(r){process.stderr.write(`[flow-obs debug ERROR] ${r.message}
|
|
28
|
+
`);}}var Cs,U=g(()=>{"use strict";A();Cs=It.join(dt.tmpdir(),Lr);});function Fs(t){if(!$s.test(t))throw new Error(`Invalid tenant value: "${t}". Tenant must be lowercase alphanumeric and hyphens (1-64 chars).`)}function xs(t,e){let r=e.length>400?e.slice(0,400)+"\u2026":e;l("toAuthError",`status=${t} body=${r}`);try{let n=JSON.parse(e);if(typeof n.error=="string"&&(l("toAuthError",`api_error_code=${n.error}`+(n.message?` api_message=${n.message}`:"")),Ir[n.error]))return new lt(Ir[n.error])}catch{}return t===401||t===403||t===500?new lt("Invalid credentials"):t>=400&&t<500?new lt("Authentication request was rejected"):new Error("Authentication service unavailable, please try again later")}function G(t){return new Promise((e,r)=>{try{Fs(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?ws__default.default:Us__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(xs(u.statusCode??0,h));let f;try{f=JSON.parse(h);}catch{return r(new Error("Invalid response from auth engine"))}let S=f.expires_at??new Date(Date.now()+(f.expires_in??3600)*1e3).toISOString();e({accessToken:f.access_token??"",expiresAt:S});});});c.on("error",u=>r(new Error(`Network error: ${u.message}`))),c.write(n),c.end();})}var lt,$s,Ir,vt=g(()=>{"use strict";A();U();lt=class extends Error{constructor(e){super(e),this.name="AuthError";}},$s=/^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$|^[a-z0-9]$/;Ir={INVALID_CLIENT_SECRET:"Invalid Client Secret \u2014 check the value and try again",INVALID_CLIENT_ID:"Invalid Client ID \u2014 check the value and try again",INVALID_TENANT:"Invalid Tenant \u2014 check the value and try again",TENANT_NOT_FOUND:"Tenant not found \u2014 verify the tenant identifier"};});function Pr(){return process.platform==="win32"?false:process.getuid?.()===0}function ut(){if(Pr())return process.stderr.write(`
|
|
29
|
+
`+L(` \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 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{
|
|
35
|
-
`,{encoding:"utf8",mode:384});try{
|
|
36
|
-
`,{encoding:"utf8",mode:384});try{
|
|
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:
|
|
33
|
+
`),1}var Ht=g(()=>{"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 v(){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 It__namespace.join(e,".claude","settings.json")}return It__namespace.join(dt__namespace.homedir(),".claude","settings.json")}if(process.platform==="win32"){let t=process.env.USERPROFILE||dt__namespace.homedir();return It__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 It__namespace.join(e,".claude","settings.json")}return It__namespace.join(dt__namespace.homedir(),".claude","settings.json")}var fe=g(()=>{"use strict";Ht();});function me(){if(process.platform==="win32"){let r=process.env.APPDATA||It__namespace.join(dt__namespace.homedir(),"AppData","Roaming");return It__namespace.join(r,Cr,Nr)}let t=br(),e=process.env.XDG_CONFIG_HOME||It__namespace.join(t.home,".config");return It__namespace.join(e,Cr,Nr)}function Wt(){try{let t=E__namespace.readFileSync(v(),"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=E__namespace.readFileSync(v(),"utf8");return JSON.parse(t).env??null}catch{return null}}var Cr,Nr,Ke=g(()=>{"use strict";fe();Cr="flow-ai-obs",Nr="config.json";});function ge(t){try{let e=E__namespace.statSync(t);Date.now()-e.mtimeMs>Ds&&E__namespace.unlinkSync(t);}catch{}try{E__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 he(t){try{E__namespace.unlinkSync(t);}catch{}}function Fr(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 xr(){let t=v(),e=t+".lock",r=[];E__namespace.mkdirSync(It__namespace.dirname(t),{recursive:true}),ge(e);try{if(E__namespace.existsSync(t)){E__namespace.copyFileSync(t,t+".bkp");try{E__namespace.chmodSync(t+".bkp",384);}catch{}}let n=me();if(E__namespace.existsSync(n)){let u=n+".bkp";E__namespace.copyFileSync(n,u);try{E__namespace.chmodSync(u,384);}catch{}}let s={};try{s=JSON.parse(E__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,...Bt()},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=Fr(c[u],i(u,We[u]));d.length>1&&r.push(u),c[u]=d;}E__namespace.writeFileSync(t,JSON.stringify(s,null,2)+`
|
|
34
|
+
`,{encoding:"utf8",mode:384});try{E__namespace.chmodSync(t,384);}catch{}}finally{he(e);}return {settingsPath:t,preserved:r}}function Lt(t){try{let e=E__namespace.readFileSync(v(),"utf8"),n=JSON.parse(e).env?.[t];return typeof n=="string"?n:null}catch{return null}}function B(t){let e=v(),r=e+".lock";E__namespace.mkdirSync(It__namespace.dirname(e),{recursive:true}),ge(r);try{let n={};try{n=JSON.parse(E__namespace.readFileSync(e,"utf8"));}catch{}(!n.env||typeof n.env!="object")&&(n.env={}),Object.assign(n.env,t),E__namespace.writeFileSync(e,JSON.stringify(n,null,2)+`
|
|
35
|
+
`,{encoding:"utf8",mode:384});try{E__namespace.chmodSync(e,384);}catch{}}finally{he(r);}}function Dr(){let t=v(),e=t+".lock",r=[];E__namespace.mkdirSync(It__namespace.dirname(t),{recursive:true}),ge(e);try{if(E__namespace.existsSync(t)){E__namespace.copyFileSync(t,t+".bkp");try{E__namespace.chmodSync(t+".bkp",384);}catch{}}let n={};try{n=JSON.parse(E__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=Fr(i[a],s(a,We[a]));c.length>1&&r.push(a),i[a]=c;}E__namespace.writeFileSync(t,JSON.stringify(n,null,2)+`
|
|
36
|
+
`,{encoding:"utf8",mode:384});try{E__namespace.chmodSync(t,384);}catch{}}finally{he(e);}return {settingsPath:t,preserved:r}}function Mr(t){let e=v(),r=e+".lock";E__namespace.mkdirSync(It__namespace.dirname(e),{recursive:true}),ge(r);try{let n={};try{n=JSON.parse(E__namespace.readFileSync(e,"utf8"));}catch{return}if(!n.env||typeof n.env!="object")return;for(let s of t)delete n.env[s];E__namespace.writeFileSync(e,JSON.stringify(n,null,2)+`
|
|
37
|
+
`,{encoding:"utf8",mode:384});try{E__namespace.chmodSync(e,384);}catch{}}finally{he(r);}}var Ds,Yt=g(()=>{"use strict";A();vt();fe();Ke();Ds=Rr.LOCK_STALE_MS;});function Gt(){let t=dt__namespace.default.homedir();if(process.platform==="darwin")return It__namespace.default.join(t,"Library","Preferences",de,pe);if(process.platform==="win32"){let r=process.env.APPDATA??It__namespace.default.join(t,"AppData","Roaming");return It__namespace.default.join(r,de,pe)}let e=process.env.XDG_CONFIG_HOME??It__namespace.default.join(t,".config");return It__namespace.default.join(e,de,pe)}function qe(){try{let t=E__namespace.default.readFileSync(Gt(),"utf8");return JSON.parse(t)}catch{return {}}}function Br(t){let e=Gt();E__namespace.default.mkdirSync(It__namespace.default.dirname(e),{recursive:true}),E__namespace.default.writeFileSync(e,JSON.stringify(t,null,2),{encoding:"utf8",mode:384});}var Je,Ee,Hr=g(()=>{"use strict";A();Je={credentials:"credentials","token-cache":"tokenCache"};Ee=class{static isAvailable(){return !0}static hasExistingData(){try{if(!E__namespace.default.existsSync(Gt()))return !1;let e=JSON.parse(E__namespace.default.readFileSync(Gt(),"utf8"));return !!(e&&e.credentials)}catch{return !1}}async getSecret(e,r){let n=qe(),s=Je[r]??r,o=n[s];return o?typeof o=="string"?o:JSON.stringify(o):null}async setSecret(e,r,n){let s=qe(),o=Je[r]??r;if(r==="token-cache")try{s[o]=JSON.parse(n);}catch{s[o]=n;}else s[o]=n;Br(s);}async deleteSecret(e,r){let n=qe(),s=Je[r]??r;return s in n?(delete n[s],Br(n),!0):!1}getStoragePath(){return `config.json (unencrypted) \u2014 ${Gt()}`}};});var jr={};W(jr,{MacOsKeyVaultProvider:()=>Xe});var ze,Xe,Wr=g(()=>{"use strict";ze=util.promisify(child_process.execFile),Xe=class{static async isAvailable(){try{return E.accessSync("/usr/bin/security",E.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 Yr={};W(Yr,{LinuxKeyVaultProvider:()=>Ze});var Vr,Ze,Gr=g(()=>{"use strict";Vr=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 E.accessSync(r,E.constants.X_OK),!0}catch{}return !1}async getSecret(e,r){try{let{stdout:n}=await Vr("secret-tool",["lookup","service",e,"account",r]);return n.trim()||null}catch{return null}}async setSecret(e,r,n){await new Promise((s,o)=>{let i=child_process.spawn("secret-tool",["store","--label",e,"service",e,"account",r]);i.on("error",o),i.on("close",a=>{a===0?s():o(new Error(`secret-tool exited with code ${a}`));}),i.stdin.write(n),i.stdin.end();});}async deleteSecret(e,r){try{return await Vr("secret-tool",["clear","service",e,"account",r]),!0}catch{return !1}}getStoragePath(){return "Linux Secret Service (libsecret)"}};});var Kr={};W(Kr,{WindowsKeyVaultProvider:()=>Qe});var Qe,Jr=g(()=>{"use strict";Qe=class{static async isAvailable(){try{return await Dt("keytar").getPassword("__flow_probe__","__flow_probe__"),!0}catch{return !1}}async getSecret(e,r){return Dt("keytar").getPassword(e,r)}async setSecret(e,r,n){await Dt("keytar").setPassword(e,r,n);}async deleteSecret(e,r){return Dt("keytar").deletePassword(e,r)}getStoragePath(){return "Windows Credential Manager"}};});async function qr(){return await qs()??new Ee}async function qs(){switch(process.platform){case "darwin":{let{MacOsKeyVaultProvider:t}=await Promise.resolve().then(()=>(Wr(),jr));return await t.isAvailable()?new t:null}case "linux":{let{LinuxKeyVaultProvider:t}=await Promise.resolve().then(()=>(Gr(),Yr));return await t.isAvailable()?new t:null}case "win32":{let{WindowsKeyVaultProvider:t}=await Promise.resolve().then(()=>(Jr(),Kr));return await t.isAvailable()?new t:null}default:return null}}var zr=g(()=>{"use strict";Hr();});function Qr(){return tr||(tr=qr()),tr}async function Jt(t){await(await Qr()).setSecret(Xr,Zr,JSON.stringify({accessToken:t.accessToken,expiresAt:t.expiresAt,lastAuthCheckAt:t.lastAuthCheckAt}));}async function Pt(){let e=await(await Qr()).getSecret(Xr,Zr);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 we(){let t=await Pt();return t?new Date(t.expiresAt)>new Date:false}async function qt(){let t=await Pt();if(!t||!t.accessToken)return null;try{let e=t.accessToken.split(".");if(e.length<2)return null;let r=JSON.parse(Buffer.from(e[1].replace(/-/g,"+").replace(/_/g,"/"),"base64").toString("utf8"));return r.email??r.preferred_username??r.upn??r.sub??null}catch{return null}}var Xr,na,Zr,tr,Se=g(()=>{"use strict";zr();A();Xr=ue.SERVICE,na=ue.ACCOUNT_CREDS,Zr=ue.ACCOUNT_TOKEN,tr=null;});function Zs(t){return Xs.some(e=>e.test(t))}function Qs(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 rn(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&&Zs(e.hostname))throw new Error(`SSRF: private/loopback host not allowed: ${e.hostname}`);return t}async function nn(){let t=b(process.env[p.ANTHROPIC_AUTH_TOKEN]);return t?{user:await qt().catch(()=>null)??t.clientId,tenant:t.tenant}:{user:"",tenant:""}}function to(){return new Date().toISOString().slice(0,10)}async function eo(t){let e=to(),r=await Pt();if(r?.lastAuthCheckAt!==e){l("getOrRefreshToken",`daily auth check (last: ${r?.lastAuthCheckAt??"never"})`);try{let o=await G(t);try{await Jt({...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 G(t);try{await Jt({...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 ro(t,e){let r=e&&e.accessToken?e.accessToken:"";return {endpoint:t.replace(/\/$/,"")+"/flow-langfuse-gateway/v1/traces",authHeader:`Bearer ${r}`}}function no(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 f="",S=n;r&&(f=await qt().catch(()=>null)??r.clientId);let k={user:f??"",tenant:S??"",team:"",project:"",model:e};t.push({mode:"direct",...no(pt(o),i,a),...k}),l("resolveCredentials","direct mode active",`user=${k.user}`,`tenant=${k.tenant}`);}if(!r){if(t.length===0){let f=[];return f.authError=false,f}return t}let c;try{c=await eo(r);}catch(f){if(l("resolveCredentials",`token refresh failed: ${f.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:Qs(c)??r.clientId,tenant:n,team:"",project:"",model:e},h=process.env[p.FLOW_TELEMETRY_GATEWAY]??ct();return t.push({mode:"gateway",...ro(pt(h),{accessToken:c}),...d}),t}async function sn(){return (await J()).length>0}function bt(){let t=process.env[p.FLOW_USER_EMAIL];if(t)return l("resolveUserEmail","using FLOW_USER_EMAIL override: [REDACTED]"),t.replace(/[\r\n]/g,"").trim();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"),tn||(tn=!0,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: [REDACTED]"),n}catch(e){return l("resolveUserEmail",`os.userInfo() threw: ${e.message} \u2014 omitting x-flow-user`),en||(en=true,console.warn("[flow-ai-obs] Could not derive x-flow-user from OS username. Set FLOW_USER_EMAIL to fix this.")),null}}function Te(){let t=process.env.OTEL_EXPORTER_OTLP_HEADERS;return t?t.replace(/[\r\n]/g,"").trim():null}var Xs,tn,en,H=g(()=>{"use strict";Se();vt();A();U();Xs=[/^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];tn=!1,en=!1;});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 rr(){try{if(process.env.WSL_DISTRO_NAME&&process.platform==="linux"){let e=child_process.spawnSync("cmd.exe",["/c","claude","--version"],{encoding:"utf8",timeout:5e3});return e.status===0?e.stdout.trim():null}let t=child_process.spawnSync("claude",["--version"],{encoding:"utf8",timeout:5e3});return t.status===0?t.stdout.trim():null}catch{return null}}function on(){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",er],{encoding:"utf8",stdio:["inherit","inherit","pipe"],timeout:12e4});if(e.status===0)return {success:true};let r=String(e.stderr??""),n=e.error,s=n instanceof Error?n.message:r;return s.includes("EACCES")||s.includes("permission denied")||s.includes("EPERM")||r.includes("EACCES")||r.includes("EPERM")?{success:false,error:"permission_denied",message:process.platform==="win32"?`Run this terminal as Administrator and try again:
|
|
41
|
+
npm install -g ${er}`:`Try with elevated permissions:
|
|
42
|
+
sudo npm install -g ${er}`}:{success:false,error:"unknown",message:s||"npm install failed"}}var er,nr=g(()=>{"use strict";er="@anthropic-ai/claude-code";});function sr(){return It__namespace.default.join(dt__namespace.default.homedir(),".claude","flow-obs",".logged-out")}function cn(){try{let t=sr();E__namespace.default.mkdirSync(It__namespace.default.dirname(t),{recursive:!0}),E__namespace.default.writeFileSync(t,"",{mode:384});}catch{}}function ln(){try{E__namespace.default.unlinkSync(sr());}catch{}}function or(){try{return E__namespace.default.existsSync(sr())}catch{return false}}var un=g(()=>{"use strict";});var ir={};W(ir,{promptRaw:()=>z,runLogin:()=>ft,runLogout:()=>lo,runStatus:()=>uo});function X(t){return typeof t=="string"?t.replace(oo,""):t}function z(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 dn(t){let{accessToken:e,expiresAt:r}=await G(t),n=rn(t);B({[p.ANTHROPIC_AUTH_TOKEN]:n}),ln(),await Jt({accessToken:e,expiresAt:r});}async function io(t){try{return await dn(t),process.stdout.write(R(` \u2713 Setup complete. Tenant: ${X(t.tenant)}
|
|
45
45
|
|
|
46
|
-
`)),0}catch(e){return process.stderr.write(
|
|
47
|
-
`)),1}}async function
|
|
48
|
-
`);let t=(await
|
|
49
|
-
`)),1;try{await
|
|
50
|
-
`)),1}return process.stdout.write(
|
|
46
|
+
`)),0}catch(e){return process.stderr.write(L(` \u2717 Authentication failed: ${X(e.message)}
|
|
47
|
+
`)),1}}async function ao(){try{process.stdout.write(`
|
|
48
|
+
`);let t=(await z(I(" ? ")+"Client ID: ")).trim(),e=(await z(I(" ? ")+"Client Secret: ",{masked:!0})).trim(),r=(await z(I(" ? ")+"Tenant: ")).trim();if(!t||!e||!r)return process.stderr.write(L(` \u2717 All fields are required
|
|
49
|
+
`)),1;try{await dn({clientId:t,clientSecret:e,tenant:r});}catch(n){return process.stderr.write(L(` \u2717 Authentication failed: ${X(n.message)}
|
|
50
|
+
`)),1}return process.stdout.write(R(` \u2713 Setup complete. Tenant: ${X(r)}
|
|
51
51
|
`)),process.stdout.write(` Storage: ANTHROPIC_AUTH_TOKEN (settings.json)
|
|
52
52
|
|
|
53
|
-
`),0}catch(t){if(t.message==="SIGINT"||t.message==="NOT_A_TTY")throw t;return process.stderr.write(
|
|
54
|
-
`)),1}}async function
|
|
55
|
-
`),process.stdout.write(
|
|
56
|
-
`)),process.stdout.write(w(" Tenant: ")+
|
|
57
|
-
`),process.stdout.write(w(" Client ID: ")+
|
|
53
|
+
`),0}catch(t){if(t.message==="SIGINT"||t.message==="NOT_A_TTY")throw t;return process.stderr.write(L(` \u2717 Unexpected error: ${t.message}
|
|
54
|
+
`)),1}}async function ft(t={}){let e=ut();if(e)return e;if(t.clientId&&t.clientSecret&&t.tenant)return io({clientId:t.clientId,clientSecret:t.clientSecret,tenant:t.tenant});let n=or()?null:b(Lt(p.ANTHROPIC_AUTH_TOKEN)??process.env[p.ANTHROPIC_AUTH_TOKEN]);if(n){process.stdout.write(`
|
|
55
|
+
`),process.stdout.write(C(` Already authenticated
|
|
56
|
+
`)),process.stdout.write(w(" Tenant: ")+X(n.tenant)+`
|
|
57
|
+
`),process.stdout.write(w(" Client ID: ")+X(n.clientId)+`
|
|
58
58
|
`),process.stdout.write(`
|
|
59
|
-
`);let s;try{s=await
|
|
60
|
-
`),130;if(o.message==="NOT_A_TTY")return process.stdout.write(
|
|
59
|
+
`);let s;try{s=await z(I(" ? ")+"Re-authenticate? (y/N): ");}catch(o){if(o.message==="SIGINT")return process.stdout.write(`
|
|
60
|
+
`),130;if(o.message==="NOT_A_TTY")return process.stdout.write(R(` \u2713 Using existing credentials.
|
|
61
61
|
|
|
62
|
-
`)),0;throw o}if(s.trim().toLowerCase()!=="y")return process.stdout.write(
|
|
62
|
+
`)),0;throw o}if(s.trim().toLowerCase()!=="y")return process.stdout.write(R(` \u2713 Using existing credentials.
|
|
63
63
|
|
|
64
|
-
`)),0}try{return await
|
|
65
|
-
`),130;if(s.message==="NOT_A_TTY")return process.stderr.write(
|
|
66
|
-
`)+" Pass --client-id, --client-secret and --tenant, or run `flow-ai-obs auth login` in a terminal.\n\n"),1;throw s}}async function
|
|
67
|
-
`),(await
|
|
64
|
+
`)),0}try{return await ao()}catch(s){if(s.message==="SIGINT")return process.stdout.write(`
|
|
65
|
+
`),130;if(s.message==="NOT_A_TTY")return process.stderr.write(L(` \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 co(){try{return process.stdout.write(`
|
|
67
|
+
`),(await z(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
|
|
71
|
-
`)),0}catch{return process.stderr.write(
|
|
72
|
-
`)),1}}async function
|
|
73
|
-
`+
|
|
74
|
-
`)),process.stdout.write(w(" Tenant: ")+
|
|
75
|
-
`),process.stdout.write(w(" Client ID: ")+
|
|
69
|
+
`),130;throw t}}async function lo(t=false){let e=ut();if(e)return e;if(!b(Lt(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 co();if(n!==null)return n}try{return Mr([p.ANTHROPIC_AUTH_TOKEN]),delete process.env[p.ANTHROPIC_AUTH_TOKEN],cn(),process.stdout.write(R(` \u2713 Credentials removed successfully
|
|
71
|
+
`)),0}catch{return process.stderr.write(L(` \u2717 Error removing credentials
|
|
72
|
+
`)),1}}async function uo(){if(or())return process.stdout.write(_(" \u26A0 Not authenticated. Run `flow-ai-obs auth login` to set up.\n")),0;let t=b(Lt(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 we())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
|
+
`+C(` Authenticated
|
|
74
|
+
`)),process.stdout.write(w(" Tenant: ")+X(t.tenant)+`
|
|
75
|
+
`),process.stdout.write(w(" Client ID: ")+X(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 oo,zt=g(()=>{"use strict";Se();un();vt();H();Yt();A();it();Ht();oo=/[\x00-\x08\x0B-\x1F\x7F]|\x1b\[[0-9;]*[a-zA-Z]/g;});var cr={};W(cr,{normalizeCustomUrl:()=>mn,runInit:()=>go,validateCustomUrl:()=>ar});function po(){try{let t=E__namespace.readFileSync(v(),"utf8"),e=JSON.parse(t);return !!(e.env&&e.env[p.ANTHROPIC_AUTH_TOKEN])}catch{return false}}function fo(){let t=Wt();if(!t)return null;B({FLOW_BASE_URL:t});try{let e=me(),r={};try{r=JSON.parse(E__namespace.readFileSync(e,"utf8"));}catch{return t}delete r.baseUrl,Object.keys(r).length===0?E__namespace.unlinkSync(e):E__namespace.writeFileSync(e,JSON.stringify(r,null,2)+`
|
|
80
|
+
`,{encoding:"utf8",mode:384});}catch{}return t}function mn(t){let e=t.trim().replace(/\\/g,"/");/^https?:\/\//i.test(e)||(e=`https://${e}`);try{let r=new URL(e);return `${r.protocol}//${r.host}`}catch{return e}}function ar(t,e=false){if(e){let o;try{o=new URL(t);}catch{throw new Error(`Invalid URL: ${t}`)}if(o.protocol!=="https:")throw new Error(`Custom URL must use HTTPS: ${t}`);if(o.pathname!=="/"&&o.pathname!=="")throw new Error(`Custom URL must be a base URL with no path beyond the root.
|
|
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=mn(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 pn(){for(let t=1;t<=3;t++)try{let e=await le(" Enter your Flow domain (e.g., tenant.ciandt.com)");return ar(e)}catch(e){if(process.stderr.write(_(` \u2717 ${e.message}
|
|
87
87
|
|
|
88
|
-
`)),t===3)throw process.stderr.write(
|
|
88
|
+
`)),t===3)throw process.stderr.write(L(` 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 mo(t,e){let r=bt(),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
|
-
`)));return}if(!r){process.stdout.write(_(`
|
|
93
|
+
`)));return}let s=o=>{let i=o.trim();return i.includes("@")?/\s/.test(i)?"Email must not contain whitespace":null:"Email must contain @"};if(!r){process.stdout.write(_(`
|
|
94
94
|
\u26A0 Could not derive email from OS username.
|
|
95
|
-
`));let
|
|
95
|
+
`));let o=await le(" Enter your corporate email",i=>s(i));B({[p.FLOW_USER_EMAIL]:o.trim()}),process.stdout.write(R(` \u2713 Email saved: ${o.trim()}
|
|
96
96
|
|
|
97
|
-
`));return}if(e)if(await
|
|
97
|
+
`));return}if(e)if(await ce(" Is your corporate email domain @ciandt.com?",true))process.stdout.write(R(` \u2713 Email: ${C(n)}
|
|
98
98
|
|
|
99
|
-
`));else {let
|
|
99
|
+
`));else {let i=await le(" Enter your corporate email",a=>s(a));B({[p.FLOW_USER_EMAIL]:i.trim()}),process.stdout.write(R(` \u2713 Email saved: ${i.trim()}
|
|
100
100
|
|
|
101
|
-
`));}else process.stdout.write(
|
|
101
|
+
`));}else process.stdout.write(R(` \u2713 Email: ${C(n)}
|
|
102
102
|
|
|
103
|
-
`));}function
|
|
104
|
-
`+
|
|
103
|
+
`));}function fn(){try{let t=E__namespace.readFileSync(v(),"utf8"),r=JSON.parse(t).env?.FLOW_BASE_URL;return typeof r=="string"&&r.trim()?r.trim():null}catch{return null}}async function go(t={}){let e=ut();if(e)return e;let r=t.url;if(!ye())return process.stderr.write(`
|
|
104
|
+
`+L(` \u2717 Claude Code is not installed or not found in PATH.
|
|
105
105
|
|
|
106
106
|
`)+` flow-ai-obs requires Claude Code to function.
|
|
107
107
|
Install it with:
|
|
@@ -112,35 +112,35 @@
|
|
|
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=fo();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=
|
|
120
|
-
Current base URL: ${
|
|
121
|
-
`),await
|
|
122
|
-
`),await
|
|
123
|
-
`);}if(!r&&!t.noInteractive&&!at()){let d=
|
|
124
|
-
`)+w(` Using URL: ${
|
|
119
|
+
`)),!r&&!t.noInteractive&&at()){let d=fn();try{d?(process.stdout.write(`
|
|
120
|
+
Current base URL: ${C(d)}
|
|
121
|
+
`),await ce(" Keep this URL?",!0)||(r=await pn())):(process.stdout.write(`
|
|
122
|
+
`),await ce(" Does your organization use a custom Flow URL?",!1)&&(r=await pn()));}catch{return 1}process.stdout.write(`
|
|
123
|
+
`);}if(!r&&!t.noInteractive&&!at()){let d=fn(),h=process.env.FLOW_BASE_URL,f=d??h??Mt,S=!!(d??h);process.stdout.write(_(` \u26A0 Non-interactive environment detected.
|
|
124
|
+
`)+w(` Using URL: ${f}
|
|
125
125
|
`)+(S?"":w(` Run with --custom-url to configure a custom domain.
|
|
126
126
|
`))+`
|
|
127
|
-
`);}
|
|
128
|
-
\u2717 Invalid --custom-url: ${
|
|
127
|
+
`);}let s=null,o=null;if(r){let d;try{d=ar(r,!0);}catch(St){return process.stderr.write(`
|
|
128
|
+
\u2717 Invalid --custom-url: ${St.message}
|
|
129
129
|
|
|
130
|
-
`),1}let h=Wt(),
|
|
130
|
+
`),1}let h=Wt(),f=$r(),S=`${d}/otel`,k=`${d}/flow-llm-proxy/`,O=h??Mt,wt=f?.OTEL_EXPORTER_OTLP_ENDPOINT&&f.OTEL_EXPORTER_OTLP_ENDPOINT!==`${O}/otel`,nt=f?.ANTHROPIC_BASE_URL&&f.ANTHROPIC_BASE_URL!==`${O}/flow-llm-proxy/`;o={FLOW_BASE_URL:d,OTEL_EXPORTER_OTLP_ENDPOINT:wt?f.OTEL_EXPORTER_OTLP_ENDPOINT:S,ANTHROPIC_BASE_URL:nt?f.ANTHROPIC_BASE_URL:k},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
|
-
`)):process.stdout.write(
|
|
134
|
+
`)):process.stdout.write(R(` \u2713 Base URL configured: ${d}
|
|
135
135
|
|
|
136
|
-
`));}if(!
|
|
136
|
+
`));}if(await mo(!t.noInteractive,!!(s??Wt())),!po())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(()=>(zt(),
|
|
138
|
+
`));let{runLogin:d}=await Promise.resolve().then(()=>(zt(),ir)),h=await d();if(h!==0)return h}let i,a;try{(({settingsPath:i,preserved:a}=xr())),o&&B(o);}catch(d){return process.stderr.write(` \u2717 Failed to write settings: ${d.message}
|
|
139
139
|
`),1}process.stdout.write(`
|
|
140
|
-
`+
|
|
140
|
+
`+C(" 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+`
|
|
142
142
|
`);process.stdout.write(`
|
|
143
|
-
`),process.stdout.write(
|
|
143
|
+
`),process.stdout.write(C(" Hooks registered")+` (Langfuse trace capture)
|
|
144
144
|
`),process.stdout.write(w(" UserPromptSubmit")+` \u2192 flow-ai-obs UserPromptSubmit (timeout: 5s)
|
|
145
145
|
`),process.stdout.write(w(" PreToolUse ")+` \u2192 flow-ai-obs PreToolUse (timeout: 3s)
|
|
146
146
|
`),process.stdout.write(w(" PostToolUse ")+` \u2192 flow-ai-obs PostToolUse (timeout: 10s)
|
|
@@ -152,16 +152,16 @@
|
|
|
152
152
|
`),process.stdout.write(w(" Settings: ")+i+`
|
|
153
153
|
`),process.stdout.write(w(" Backup: ")+i+`.bkp
|
|
154
154
|
`),process.stdout.write(w(" OTEL auth: flow-ai-obs otel-headers")+w(` (reads ANTHROPIC_AUTH_TOKEN from settings.json)
|
|
155
|
-
`));let u=s??Wt()??process.env.FLOW_BASE_URL??
|
|
155
|
+
`));let u=s??Wt()??process.env.FLOW_BASE_URL??Mt;return process.stdout.write(w(" Base URL: ")+u+`
|
|
156
156
|
`),process.stdout.write(`
|
|
157
|
-
`),t.skipHint||(process.stdout.write(
|
|
158
|
-
`)),process.stdout.write(w(" Run `flow-ai-obs setup` to configure a full environment from scratch.\n\n"))),0}var
|
|
159
|
-
${
|
|
160
|
-
`);}function
|
|
161
|
-
`));}function
|
|
162
|
-
`));}function
|
|
163
|
-
`));}function
|
|
164
|
-
`));}async function
|
|
157
|
+
`),t.skipHint||(process.stdout.write(R(` \u2713 Ready. Native OTEL + Langfuse trace capture active.
|
|
158
|
+
`)),process.stdout.write(w(" Run `flow-ai-obs setup` to configure a full environment from scratch.\n\n"))),0}var lr=g(()=>{"use strict";Yt();A();it();fe();Ht();H();Ke();nr();$e();});var En={};W(En,{runSetup:()=>yo});function ho(){try{return JSON.parse(E__namespace.readFileSync(v(),"utf8"))}catch{return {}}}function Eo(t){return !!(t.env??{}).ANTHROPIC_BASE_URL}function wo(t){let e=t.env??{};return Object.keys(V).every(r=>!!e[r])}function So(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 To(t){return (await z(t)).trim().toLowerCase()==="y"}function Oe(t,e,r){process.stdout.write(`
|
|
159
|
+
${C(`[${t}/${e}]`)} ${r}
|
|
160
|
+
`);}function q(t){process.stdout.write(R(` \u2713 ${t}
|
|
161
|
+
`));}function gn(t){process.stdout.write(_(` \u26A0 ${t}
|
|
162
|
+
`));}function Xt(t){process.stderr.write(L(` \u2717 ${t}
|
|
163
|
+
`));}function mt(t){process.stdout.write(w(` ${t}
|
|
164
|
+
`));}async function yo(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,40 @@ ${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)
|
|
178
|
-
`+
|
|
179
|
-
`),
|
|
180
|
-
`)
|
|
181
|
-
`);}
|
|
182
|
-
`);}function
|
|
183
|
-
`);}function
|
|
184
|
-
`);}
|
|
185
|
-
`)
|
|
186
|
-
`);
|
|
187
|
-
`);}
|
|
188
|
-
`)
|
|
189
|
-
`);let
|
|
190
|
-
`)
|
|
191
|
-
`)
|
|
192
|
-
`)
|
|
193
|
-
`);
|
|
175
|
+
`);let n=ho();if(Oe(1,r,"Checking Claude Code..."),ye()){let s=rr();q(s?`Already installed (${s}) \u2014 skipping.`:"Already installed \u2014 skipping.");}else {mt("Not found. Installing via npm...");let s=on();if(!s.success)return Xt(s.message??"Failed to install Claude Code."),process.stderr.write(L(` Setup aborted at step 1. Resolve the error above and try again.
|
|
176
|
+
`)),1;let o=rr();q(o?`Claude Code ${o} installed.`:"Claude Code installed.");}if(Oe(2,r,"Configuring proxy..."),Eo(n)){let s=n.env.ANTHROPIC_BASE_URL;gn(`Proxy already configured (${s})`);let o=t.nonInteractive||!process.stdin.isTTY,i=false;if(!o)try{i=await To(I(" ? ")+"Replace existing proxy configuration? [y/N]: ");}catch(a){if(a.message==="SIGINT")return process.stdout.write(`
|
|
177
|
+
`),130;throw a}if(!i)mt("Keeping existing proxy configuration.");else {let a=await ft(t);if(a!==0)return a;try{B(Bt()),q("Proxy reconfigured.");}catch(c){return Xt(`Could not write proxy config: ${c.message}`),1}}}else {let s=await ft(t);if(s!==0)return s;try{B(Bt()),q("Proxy configured."),mt(`Settings: ${v()}`);}catch(o){return Xt(`Could not write proxy config: ${o.message}`),1}}if(Oe(3,r,"Configuring AI Usage..."),t.url){let{runInit:s}=await Promise.resolve().then(()=>(lr(),cr)),o=await s({noInteractive:true,url:t.url,skipHint:true});if(o!==0)return o;q("AI Usage configured with custom URL.");}else if(wo(n))q("Already configured \u2014 skipping.");else try{B(V),q("AI Usage configured."),mt(`Settings: ${v()}`);}catch(s){return Xt(`Could not write AI Usage config: ${s.message}`),1}if(Oe(4,r,"Configuring Langfuse..."),So(n))q("Already configured \u2014 skipping.");else {let s,o;try{({settingsPath:s,preserved:o}=Dr());}catch(i){return Xt(`Could not write hooks: ${i.message}`),1}q("Hooks registered (UserPromptSubmit, PreToolUse, PostToolUse, Stop)"),o.length>0&&(gn(`Third-party hooks preserved on: ${o.join(", ")}`),mt("flow-ai-obs was prepended \u2014 it executes first.")),mt(`Settings: ${s}`),mt(`Backup: ${s}.bkp`);}return process.stdout.write(`
|
|
178
|
+
`+R(" \u2713 Setup complete. Run `claude` to start.\n\n")),0}var wn=g(()=>{"use strict";A();it();Ht();zt();Yt();nr();});var Sn={};W(Sn,{runOtelHeaders:()=>_o});async function _o(){let t=b(process.env[p.ANTHROPIC_AUTH_TOKEN]);if(!t)return process.stderr.write(`[flow-ai-obs otel-headers] Not authenticated \u2014 run: flow-ai-obs auth login
|
|
179
|
+
`),1;let e;try{e=(await G(t)).accessToken;}catch(o){return process.stderr.write(`[flow-ai-obs otel-headers] Token fetch failed: ${o.message}
|
|
180
|
+
`),1}if(!e)return process.stderr.write(`[flow-ai-obs otel-headers] Empty token received
|
|
181
|
+
`),1;let r={Authorization:`Bearer ${e}`},n=bt();n&&(r["x-flow-user"]=n);let s=Te();return s?r["x-flow-api-key"]=s:l("otel-headers","OTEL_EXPORTER_OTLP_HEADERS not set \u2014 x-flow-api-key header omitted"),process.stdout.write(JSON.stringify(r)+`
|
|
182
|
+
`),0}var Tn=g(()=>{"use strict";vt();H();A();U();});var _n={};W(_n,{runCheck:()=>Oo});function ur(t){return !t||t.length<=8?"****":t.slice(0,4)+"****...****"+t.slice(-4)}function Zt(t){process.stdout.write(` \u2713 ${t}
|
|
183
|
+
`);}function Ae(t){process.stdout.write(` \u26A0 ${t}
|
|
184
|
+
`);}function ke(t){process.stdout.write(` \u2717 ${t}
|
|
185
|
+
`);}function $(t){process.stdout.write(` ${t}
|
|
186
|
+
`);}function F(){process.stdout.write(`
|
|
187
|
+
`);}async function Oo(){F(),process.stdout.write(` flow-claude-observability \u2014 configuration check
|
|
188
|
+
`),F(),process.stdout.write(` Auth
|
|
189
|
+
`);let t=()=>Lt(p.ANTHROPIC_AUTH_TOKEN)??process.env[p.ANTHROPIC_AUTH_TOKEN],e=b(t());if(!e){Ae("Not authenticated \u2014 starting setup..."),F();let a=await ft();if(a!==0)return a;if(e=b(t()),!e)return ke("Authentication failed"),F(),1;F(),process.stdout.write(` Auth
|
|
190
|
+
`);}if(!await we()){Ae("Session expired \u2014 re-authenticating..."),F();let a=await ft();if(a!==0)return a;F(),process.stdout.write(` Auth
|
|
191
|
+
`);}let r=await qt()||e.clientId;Zt("Authenticated"),$(`Tenant: ${e.tenant}`),$(`User: ${r}`),F(),process.stdout.write(` Native OTEL
|
|
192
|
+
`);let n={};try{let a=E__namespace.readFileSync(v(),"utf8");n=JSON.parse(a).env||{};}catch{}let s=Object.keys(V).filter(a=>!n[a]);if(s.length===0?(Zt("All OTEL env vars present in settings.json"),$(`Endpoint: ${n.OTEL_EXPORTER_OTLP_ENDPOINT}`)):(Ae(`${s.length} OTEL var(s) missing from settings.json \u2014 native metrics/logs disabled`),s.forEach(a=>ke(`Missing: ${a}`)),$("Run: flow-ai-obs init (restores missing vars automatically)")),F(),process.stdout.write(` Tracing
|
|
193
|
+
`),process.env[p.FLOW_TELEMETRY]==="true"){Zt("FLOW_TELEMETRY=true (direct mode enabled)");let a=[p.LANGFUSE_BASE_URL,p.LANGFUSE_PUBLIC_KEY,p.LANGFUSE_SECRET_KEY].filter(c=>!process.env[c]);a.length>0&&a.forEach(c=>Ae(`Missing: ${c}`));}else $("FLOW_TELEMETRY not set \u2014 direct mode inactive (gateway mode may still be active)");let i=await J();if(!i||i.length===0)return i&&i.authError?ke("Token refresh failed \u2014 gateway mode could not activate"):(ke("No active destinations \u2014 no traces will be sent"),$("For direct mode: set FLOW_TELEMETRY=true + LANGFUSE_BASE_URL + LANGFUSE_PUBLIC_KEY + LANGFUSE_SECRET_KEY"),$("For gateway mode: run flow-claude-observability auth login")),F(),1;for(let a of i)if(a.mode==="gateway"){let c=await Pt();Zt("Mode: gateway"),$(`Endpoint: ${a.endpoint}`),$(`Token: ${ur(c?.accessToken)}`);}else a.mode==="direct"&&(Zt("Mode: direct"),$(`Endpoint: ${a.endpoint}`),$(`PK: ${ur(process.env[p.LANGFUSE_PUBLIC_KEY])}`),$(`SK: ${ur(process.env[p.LANGFUSE_SECRET_KEY])}`));return F(),process.stdout.write(` All checks passed \u2014 observability is active.
|
|
194
|
+
`),F(),0}var On=g(()=>{"use strict";Se();H();Yt();A();zt();});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 ve(t,e=100){return String(t??"").split(`
|
|
195
|
+
`)[0].slice(0,e).trim()}function dr(){return new Promise(t=>{let e="";process.stdin.setEncoding("utf8"),process.stdin.on("data",r=>{e+=r;}),process.stdin.on("end",()=>{try{t(JSON.parse(e));}catch{t({});}});})}function j(t){process.stdout.write(JSON.stringify(t));}var Nt=g(()=>{"use strict";});function Q(){return String(BigInt(Date.now())*1000000n)}var pr,gt,Qt=g(()=>{"use strict";pr=()=>crypto.randomBytes(16).toString("hex"),gt=()=>crypto.randomBytes(8).toString("hex");});function Uo(t,e){let r=It.resolve(t);if(!r.startsWith(e))throw new Error(`Path traversal detected: ${t}`);return r}function fr(t){if(!Co.test(t))throw new Error(`Invalid session ID: ${t}`);return Uo(It.join(dt.tmpdir(),`flow-obs-${t}.json`),No)}function Ut(t){let e=fr(t);if(!E.existsSync(e))return null;try{return JSON.parse(E.readFileSync(e,"utf8"))}catch{return null}}function $t(t,e){E.writeFileSync(fr(t),JSON.stringify(e),{encoding:"utf8",mode:384});}function mr(t){try{E.unlinkSync(fr(t));}catch{}}var Co,No,te=g(()=>{"use strict";Co=/^[0-9a-f-]{1,64}$/i,No=It.normalize(dt.tmpdir())+It.sep;});function Ln(t){if(!t||!E.existsSync(t))return null;try{let e=E.readFileSync(t,"utf8").trimEnd().split(`
|
|
196
|
+
`);for(let r=e.length-1;r>=0;r--)try{let n=JSON.parse(e[r]);if(n.type==="user"&&n.uuid)return n.uuid}catch{}}catch{}return null}function gr(t){if(!t||!E.existsSync(t))return null;try{let e=E.readFileSync(t,"utf8").trimEnd().split(`
|
|
194
197
|
`),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
198
|
|
|
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 ${
|
|
200
|
-
${
|
|
201
|
-
${r}`},{re:/\b(AKIA[0-9A-Z]{16})\b/g,replace:()=>`AKIA${
|
|
202
|
-
`)),
|
|
203
|
-
`),process.stdout.write(JSON.stringify(e));}}var
|
|
204
|
-
`),process.exit(0);});});var
|
|
205
|
-
`),process.exit(0);}else if(
|
|
199
|
+
`),inputTokens:n,outputTokens:s}}catch{}return null}var hr=g(()=>{"use strict";});function bn(t){return t.replace(":","/")}function Re(t,e){if(!t)return null;let r=bn(t),n=[It.join(dt.homedir(),".claude","skills",r,"SKILL.md"),It.join(e??"",".claude","skills",r,"SKILL.md")];for(let s of n)if(E.existsSync(s))try{return E.readFileSync(s,"utf8")}catch{}return null}function Cn(t){return t.split(`
|
|
200
|
+
`)[0].match(/^\/([a-z][a-z0-9-]*(?::[a-z][a-z0-9-]*)?)(?:\s.*)?$/i)?.[1]??null}function Nn(t){return !!t.slashSkill||t.toolCalls.some(n=>n.tool==="Skill")?t.toolCalls.some(n=>n.tool==="Skill"&&!n.synthetic||Ho.has(n.tool))?"complete":"prerequisite_required":null}function Le(t,e){if(!t)return null;let r=bn(t),n=[It.join(dt.homedir(),".claude","skills",r),It.join(e??"",".claude","skills",r)],s=null;for(let a of n)if(E.existsSync(It.join(a,"SKILL.md"))){s=a;break}if(!s)return null;let o=[];function i(a,c){for(let u of E.readdirSync(a,{withFileTypes:true})){if(Do.has(u.name)||Bo.has(u.name)||Mo.has(It.extname(u.name)))continue;let d=c?`${c}/${u.name}`:u.name;u.isDirectory()?i(It.join(a,u.name),d):o.push(d);}}return i(s,""),o.length>0?o:null}var Do,Mo,Bo,Ho,Ie=g(()=>{"use strict";Do=new Set([".venv","__pycache__",".git","node_modules"]),Mo=new Set([".pyc",".pyo"]),Bo=new Set(["SKILL.md",".DS_Store",".gitignore"]);Ho=new Set(["Read","Write","Edit","MultiEdit","Bash","Glob","Grep","TodoWrite","WebFetch","WebSearch","Agent","Task"]);});function Vo(t){try{let e=t.split(".")[1].replace(/-/g,"+").replace(/_/g,"/");return JSON.parse(Buffer.from(e,"base64").toString())}catch{return null}}function Yo(t,e,r,n){return new Promise(s=>{let o=new URL(t),i=o.protocol==="https:",a=(i?ws__default.default:Us__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 ht(t,e={}){try{let r=b(process.env[p.ANTHROPIC_AUTH_TOKEN]);if(!r)return;let n,s=new Promise((h,f)=>{n=setTimeout(()=>f(new Error("getToken timeout")),4e3),n.unref();}),{accessToken:o}=await Promise.race([G(r),s]);clearTimeout(n);let i=Vo(o);if(!i)return;let a=i.tenant||r.tenant,c=JSON.stringify({action:t,booster:Ve().BOOSTER,metadata:e,success:!0,tenant:a,timestamp:new Date().toISOString(),os:process.platform,user:{email:i.email||"",id:i.sub||"",name:i.name||i.email||""}}),u=pt(Ve().API_URL),d=await Yo(u,c,o,a);l("metrics.logEvent",`action=${t} status=${d}`);}catch(r){l("metrics.logEvent",`silenced error: ${r.message}`);}}var Pe=g(()=>{"use strict";A();vt();H();U();});async function Er(t,e=false){if(e){process.stdout.write(JSON.stringify({decision:"block",reason:Go})+`
|
|
201
|
+
`);return}let n=!!(await J()).authError,s=t.session_id||"unknown",o=t.prompt||"",i=t.cwd||"",a=Ln(t.transcript_path)||pr(),c=Cn(o),u=c?Re(c,i):null,d=c?Le(c,i):null;$t(s,{traceId:pr(),spanId:gt(),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}),ht("SESSION_STARTED",{traceType:c?"skill":"prompt",slashSkill:c,clientIdExpired:n}),l("UserPromptSubmit",`sid=${s}`,`traceName=${a}`,`slashSkill=${c}`),j(t);}var Go,Un=g(()=>{"use strict";Qt();te();hr();Ie();Nt();U();A();H();Pe();Go=`\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 $n(t){let e=t.session_id||"unknown",r=t.tool_name||"unknown",n=t.tool_input||{},s=Ut(e);s&&(s.pendingTool={name:r,inputStr:K(n,Y.TOOL_INPUT),startNs:Q()},$t(e,s)),l("PreToolUse",`sid=${e}`,`tool=${r}`,`stateFound=${!!s}`),j(t);}var Fn=g(()=>{"use strict";Qt();te();Nt();U();A();});function m(t,e){return e==null||e===""?null:{key:t,value:{stringValue:String(e)}}}function Et(...t){return t.filter(e=>e!==null)}function xn(t,e){return {resourceSpans:[{resource:{attributes:t},scopeSpans:[{scope:Ko,spans:Array.isArray(e)?e:[e]}]}]}}var Ko,y,Dn=g(()=>{"use strict";A();Ko={name:je.SCOPE_NAME,version:je.SCOPE_VERSION},y={TRACE_NAME:"langfuse.trace.name",TRACE_INPUT:"langfuse.trace.input",TRACE_OUTPUT:"langfuse.trace.output",TRACE_METADATA:"langfuse.trace.metadata",TRACE_TAGS:"langfuse.trace.tags",USER_ID:"langfuse.user.id",SESSION_ID:"langfuse.session.id",OBS_NAME:"langfuse.observation.name",OBS_INPUT:"langfuse.observation.input",OBS_OUTPUT:"langfuse.observation.output",OBS_LEVEL:"langfuse.observation.level",OBS_TYPE:"langfuse.observation.type",MODEL:"gen_ai.request.model",INPUT_TOKENS:"gen_ai.usage.input_tokens",OUTPUT_TOKENS:"gen_ai.usage.output_tokens"};});function Bn(t,e,r,n,s){if(process.env[p.FLOW_OBS_DEBUG]!=="1")return;let o={...e};"Authorization"in o&&(o.Authorization="[REDACTED]"),"x-flow-user"in o&&(o["x-flow-user"]="[REDACTED]"),"x-flow-api-key"in o&&(o["x-flow-api-key"]="[REDACTED]");let i=JSON.stringify({ts:new Date().toISOString(),request:{method:"POST",url:t,headers:o,body:JSON.parse(r)},response:{status:n,body:s}});try{E.writeFileSync(Mn,i+`
|
|
202
|
+
`,{flag:"a",encoding:"utf8",mode:384}),l("sendTraces:dump",`request appendada em ${Mn}`);}catch(a){l("sendTraces:dump",`falha ao salvar: ${a.message}`);}}function Qo(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 Hn(t,e){return new Promise((r,n)=>{let s=t._isSSL?ws__default.default:Us__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 jn(t,e){let r;try{r=Qo(t);}catch{return false}let n=r.protocol==="https:";try{let s={};e&&(s.Authorization=String(e).replace(/[\r\n]/g,""));let o=await Hn({hostname:r.hostname,port:r.port||(n?443:80),path:r.pathname,method:"GET",headers:s,_isSSL:n},null);return l("checkHealth",`url=${r.href} status=${o.statusCode}`),o.statusCode>=200&&o.statusCode<300}catch{return false}}async function be(t,e,r){let n=JSON.stringify(t),s=new URL(e),o=s.protocol==="https:",i=String(r).replace(/[\r\n]/g,""),a=f=>f.replace(/[\r\n]/g,""),c=bt(),u=Te(),d={...c?{"x-flow-user":a(c)}:{},...u?{"x-flow-api-key":a(u)}:{}},h={"Content-Type":"application/json",Authorization:i,"Content-Length":Buffer.byteLength(n),...d};l("sendTraces:request",`POST ${e}`),l("sendTraces:request",`headers=${JSON.stringify({...h,Authorization:i.slice(0,20)+"\u2026","x-flow-user":c?"[REDACTED]":void 0,"x-flow-api-key":u?"[REDACTED]":void 0})}`),l("sendTraces:request",`body=${n.slice(0,500)}${n.length>500?"\u2026":""}`);try{let f=await Hn({hostname:s.hostname,port:s.port||(o?443:80),path:s.pathname,method:"POST",headers:h,_isSSL:o},n);return l("sendTraces:response",`status=${f.statusCode}`),Bn(e,h,n,f.statusCode,f.body),f.statusCode}catch(f){return l("sendTraces:error",f.message),Bn(e,h,n,0,f.message),0}}var Mn,Wn=g(()=>{"use strict";A();U();H();Mn=It.join(dt.tmpdir(),"flow-obs-requests.ndjson");});function ti(){let t=parseInt(process.env[p.BUFFER_TTL_DAYS]??"",10);return (Number.isFinite(t)?Math.max(M.MIN_TTL_DAYS,Math.min(M.MAX_TTL_DAYS,t)):M.DEFAULT_TTL_DAYS)*24*60*60*1e3}function ei(){let t=parseInt(process.env[p.BUFFER_MAX_FILES]??"",10);return Number.isFinite(t)?Math.max(M.MIN_MAX_FILES,Math.min(M.MAX_MAX_FILES,t)):M.DEFAULT_MAX_FILES}function Yn(t){if(/[/\\]/.test(t))throw new Error(`Invalid buffer fileId: ${t}`);return It__namespace.default.join(dt__namespace.default.tmpdir(),`${M.FILE_PREFIX}${t}.json`)}function Sr(){let t=dt__namespace.default.tmpdir(),e;try{e=E__namespace.default.readdirSync(t);}catch{return []}return e.filter(r=>r.startsWith(M.FILE_PREFIX)&&r.endsWith(".json")).map(r=>{let n=It__namespace.default.join(t,r),s=0;try{s=E__namespace.default.statSync(n).mtimeMs;}catch{}return {full:n,mtime:s}}).sort((r,n)=>r.mtime-n.mtime).map(r=>r.full)}function ee(t){try{let e=ei(),r=Sr();if(r.length>=e){let o=r.slice(0,r.length-e+1);for(let i of o)try{E__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 E__namespace.default.writeFileSync(Yn(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 Gn(t){let e=Sr(),r=t!=null&&t>0?t:e.length,n=[];for(let s of e){if(n.length>=r)break;try{let o=E__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 Kn(t){try{E__namespace.default.unlinkSync(Yn(t)),l("buffer",`deleted fileId=${t}`);}catch{}}function Jn(){let t=Date.now()-ti();for(let e of Sr())try{let{mtimeMs:r}=E__namespace.default.statSync(e);r<t&&(E__namespace.default.unlinkSync(e),l("buffer",`evicted stale: ${It__namespace.default.basename(e)}`));}catch{}}var qn=g(()=>{"use strict";A();U();});async function ri(t){Jn();let e=Gn(M.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,t.authHeader);n>=200&&n<300?(Kn(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 zn(t){let e=await J();if(!e.length)return e.authError&&(l("postToLangfuse","auth refresh failed \u2014 buffering trace"),ee(t)),0;let r=await Promise.all(e.map(async o=>{if(o.mode!=="gateway")return {creds:o,healthy:true};let i=await jn(o.endpoint,o.authHeader);return {creds:o,healthy:i}})),n=r.find(o=>o.creds.mode==="gateway"&&o.healthy)?.creds??r.find(o=>o.creds.mode==="direct")?.creds;return n&&await ri(n),(await Promise.all(r.map(async({creds:o,healthy:i})=>{if(o.mode==="gateway"){if(!i)return l("postToLangfuse","gateway health check failed \u2014 buffering trace"),ee(t),0;let c=await be(t,o.endpoint,o.authHeader);return (c===0||c>=500)&&(l("postToLangfuse",`gateway send failed (status ${c}) \u2014 buffering trace`),ee(t)),c}let a=await be(t,o.endpoint,o.authHeader);return (a===0||a>=500)&&(l("postToLangfuse",`direct endpoint unavailable (status ${a}) \u2014 buffering trace`),ee(t)),a}))).find(o=>o!==0)??0}var Xn=g(()=>{"use strict";H();U();Wn();qn();A();});var Tr=g(()=>{"use strict";Dn();Xn();});function et(t){if(t==null)return "";let e=typeof t=="string"?t:JSON.stringify(t);return ii.reduce((r,{re:n,replace:s})=>r.replace(n,s),e)}var x,ni,si,oi,Zn,ii,yr=g(()=>{"use strict";x="[REDACTED]",ni="[REDACTED-EMAIL]",si="[REDACTED-CPF]",oi="[REDACTED-CNPJ]",Zn="[REDACTED-PHONE]",ii=[{re:/\b(sk-[A-Za-z0-9_\-]{20,})/g,replace:()=>`sk-${x}`},{re:/\b(pk-[A-Za-z0-9_\-]{20,})/g,replace:()=>`pk-${x}`},{re:/\b(Bearer\s+)[A-Za-z0-9\-._~+/]+=*/gi,replace:(t,e)=>`${e}${x}`},{re:/\b(Basic\s+)[A-Za-z0-9+/]+=*/gi,replace:(t,e)=>`${e}${x}`},{re:/(-----BEGIN [A-Z ]+-----)[^-]*(-----END [A-Z ]+-----)/g,replace:(t,e,r)=>`${e}
|
|
203
|
+
${x}
|
|
204
|
+
${r}`},{re:/\b(AKIA[0-9A-Z]{16})\b/g,replace:()=>`AKIA${x}`},{re:/(aws_secret_access_key\s*[=:]\s*)([A-Za-z0-9/+]{40})/gi,replace:(t,e)=>`${e}${x}`},{re:/\b(ghp_[A-Za-z0-9]{36,})/g,replace:()=>`ghp_${x}`},{re:/\b(github_pat_[A-Za-z0-9_]{36,})/gi,replace:()=>`github_pat_${x}`},{re:/\b(eyJ[A-Za-z0-9_\-]+\.eyJ[A-Za-z0-9_\-]+\.[A-Za-z0-9_\-]+)/g,replace:()=>`eyJ.${x}`},{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}${x}${r}`},{re:/([a-z][a-z0-9+\-.]*:\/\/[^:/?#\s]*):([^@\s]+)@/gi,replace:(t,e)=>`${e}:${x}@`},{re:/[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}/g,replace:()=>ni},{re:/\b\d{3}\.\d{3}\.\d{3}-\d{2}\b/g,replace:()=>si},{re:/\b\d{2}\.\d{3}\.\d{3}\/\d{4}-\d{2}\b/g,replace:()=>oi},{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 Qn(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=Ut(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:K(n,Y.TOOL_INPUT),f=h,S=null;if(r==="Skill"){let ie=typeof n=="object"&&n!==null?n.skill||n.name||n.skillName||n.commandName||String(Object.values(n)[0]??""):String(n);S=ie?String(ie).trim():null;let st=S?Re(S,i.cwd):null;st&&(f=st,i.skillContent||(i.skillContent=st),i.skillArtifacts||(i.skillArtifacts=Le(S,i.cwd))),S&&!i.slashSkill&&(i.slashSkill=S),l("PostToolUse","Skill tool detected",`skillName=${S}`,`contentFound=${!!st}`);}let k=et(K(o,Y.TOOL_OUTPUT)),O=/\b(error|exception|failed|failure|traceback|errno)\b/i.test(k.slice(0,500)),wt=O?"ERROR":"DEFAULT",nt=gt(),St=Math.round(Number(BigInt(a)-BigInt(d))/1e6),se={Agent:"AGENT",Task:"AGENT"}[r]??"TOOL",oe=r==="Skill"&&S?S:ve(h,60);i.toolCalls.push({tool:r,brief:oe,error:O,durationMs:St});let xt=i.spans;xt.push({traceId:i.traceId,spanId:nt,parentSpanId:i.spanId,name:r,kind:3,startTimeUnixNano:d,endTimeUnixNano:a,attributes:Et(m(y.OBS_NAME,r),m(y.OBS_TYPE,se),m(y.OBS_LEVEL,wt),m(y.OBS_INPUT,et(f)),m(y.OBS_OUTPUT,k),m("tool.name",r),m("tool.error",String(O)),r==="Skill"&&S?m("skill.name",S):null,r==="Skill"?m("skill.invocation","slash-command"):null),status:{code:O?2:1}}),i.pendingTool=null,$t(e,i),O&&ht("TOOL_ERROR",{toolName:r}),l("PostToolUse",`sid=${e}`,`tool=${r}`,`error=${O}`,`durationMs=${St}`,`totalSpans=${xt.length}`),j(t);}var ts=g(()=>{"use strict";Qt();te();Tr();Nt();Ie();U();A();yr();Pe();});function rs(t,e,r){let n=Object.keys(es).find(i=>(t??"").toLowerCase().includes(i));if(!n)return;let s=es[n],o=(e*s.input+r*s.output)/1e6;return Math.round(o*1e6)/1e6}var es,ns=g(()=>{"use strict";es={"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 ss(t){let e=t.session_id||"unknown",r=t.stop_reason||"end_turn",n=Ut(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 nn(),i=n.toolCalls,a=n.spans;if(n.slashSkill&&!i.some(T=>T.tool==="Skill")){let T=gt(),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:Et(m(y.OBS_NAME,"Skill"),m(y.OBS_TYPE,"TOOL"),m(y.OBS_LEVEL,"DEFAULT"),m(y.OBS_INPUT,ot),m(y.OBS_OUTPUT,"loaded via slash command"),m("tool.name","Skill"),m("tool.error","false"),m("skill.name",n.slashSkill),m("skill.invocation","slash-command")),status:{code:1}}),l("Stop",`slashSkill=${n.slashSkill}`,"synthetic span injected");}let c=t.transcript_path||n.transcriptPath||"",u=gr(c);if(c&&(i.some(T=>T.tool==="Skill"&&!T.synthetic)||!!n.slashSkill)&&!u?.text){await new Promise(ot=>setTimeout(ot,500));let T=gr(c);T?.text&&(u=T);}l("Stop",`transcriptPath=${c||"(empty)"}`,`assistantOut=${u?`text=${u.text.length}chars`:"null"}`);let h=i.length,f=i.filter(T=>T.error).length,S=et(u?.text?K(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(`
|
|
205
|
+
`)),k=u?.inputTokens??0,O=u?.outputTokens??0,wt=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")),St=i.some(T=>T.tool==="Agent");if(!nt&&!St){l("Stop",`sid=${e}`,"skipping trace \u2014 no Skill or Agent calls found"),ht("TRACE_SKIPPED",{reason:"no_skill_or_agent"}),mr(e),j(t);return}let ne=nt?"skill":"agent",se=Math.round(Number(BigInt(s)-BigInt(n.startNs))/1e6),oe=rs(n.model,k,O),Tt=Nn(n);Tt==="prerequisite_required"&&u?.text&&(Tt="complete"),Tt==="prerequisite_required"&&(a.push({traceId:n.traceId,spanId:gt(),parentSpanId:n.spanId,name:"prerequisite-check",kind:3,startTimeUnixNano:n.startNs,endTimeUnixNano:s,attributes:Et(m(y.OBS_NAME,"prerequisite-check"),m(y.OBS_TYPE,"EVENT"),m(y.OBS_LEVEL,"WARNING"),m(y.OBS_OUTPUT,S),m("skill.name",n.slashSkill||void 0),m("execution_status","prerequisite_required")),status:{code:1}}),l("Stop",`sid=${e}`,"prerequisite-check span injected",`skill=${n.slashSkill}`));let xt=(()=>{if(!(!nt||!n.prompt)){if(n.slashSkill){let T=n.prompt.replace(new RegExp(`^\\/${n.slashSkill}\\s*`,"i"),"").trim();return T?K(et(T),Y.USER_INSTRUCTION):void 0}return K(et(n.prompt),Y.USER_INSTRUCTION)||void 0}})(),ie=JSON.stringify({trace_type:ne,...Tt!==null&&{execution_status:Tt},...n.slashSkill?{skill_name:n.slashSkill}:{},...n.skillArtifacts?.length&&{skill_artifacts:n.skillArtifacts},...xt!==void 0&&{user_instruction:xt},latency_ms:se,...k&&{tokens_input:k},...O&&{tokens_output:O},cost_usd:oe,...n.model?{model:n.model}:{},toolCount:h,errorCount:f,stopReason:r,sessionId:n.sessionId,tools:wt.length?wt:void 0}),st=et(K(n.prompt,Y.TRACE_INPUT)),as=Et(m(y.TRACE_NAME,n.traceName),m(y.TRACE_INPUT,st),m(y.TRACE_OUTPUT,S),m(y.OBS_INPUT,st),m(y.OBS_OUTPUT,S),m(y.TRACE_METADATA,ie),m(y.SESSION_ID,n.sessionId),m(y.USER_ID,o.user),m(y.OBS_TYPE,"GENERATION"),m(y.MODEL,n.model),k?m(y.INPUT_TOKENS,k):null,O?m(y.OUTPUT_TOKENS,O):null,m("claude.stop_reason",r),m("claude.tool_count",String(h)),m("claude.error_count",String(f)),m("claude.session_id",n.sessionId),m("flow.trace_type",ne),{key:y.TRACE_TAGS,value:{arrayValue:{values:[{stringValue:ne}]}}}),cs={traceId:n.traceId,spanId:n.spanId,name:n.traceName,kind:1,startTimeUnixNano:n.startNs,endTimeUnixNano:s,attributes:as,status:{code:f>0?2:1}},ls=Et(m("service.name",process.env.LANGFUSE_PROJECT_NAME||"claude-code"),m("deployment.environment",process.env.LANGFUSE_ENVIRONMENT||"default")),_r=[...a,cs];l("Stop",`sid=${e}`,`totalTools=${h}`,`errorTools=${f}`,`spans=${_r.length}`,`inputTokens=${k}`,`outputTokens=${O}`,`traceOutput="${ve(S,80)}"`);let us=await zn(xn(ls,_r));l("Stop",`POST status=${us}`,`traceId=${n.traceId}`),ht("TRACE_SENT",{latencyMs:se,totalTools:h,errorTools:f,inputTokens:k,outputTokens:O,costUsd:oe}),mr(e),j(t);}var os=g(()=>{"use strict";Qt();te();Tr();H();ns();hr();Nt();U();Ie();yr();A();Pe();});async function ai(){let t=process.argv[2];if(t==="UserPromptSubmit"){let r=await dr(),n;try{n=await J();}catch{process.stdout.write(JSON.stringify(r));return}n.authError?await Er(r,true):n.length>0?await Er(r):process.stdout.write(JSON.stringify(r));return}if(!await sn()){let r=[];process.stdin.on("data",n=>r.push(n)),process.stdin.on("end",()=>process.stdout.write(r.join("")));return}let e=await dr();switch(t){case "PreToolUse":await $n(e);break;case "PostToolUse":await Qn(e);break;case "Stop":await ss(e);break;default:process.stderr.write(`[flow-obs] unknown event: ${t}
|
|
206
|
+
`),process.stdout.write(JSON.stringify(e));}}var is=g(()=>{"use strict";H();Nt();Un();Fn();ts();os();ai().catch(t=>{process.stderr.write(`[flow-obs] fatal: ${t.message}
|
|
207
|
+
`),process.exit(0);});});var li=new Set(["UserPromptSubmit","PreToolUse","PostToolUse","Stop"]),[,,D,re]=process.argv;function rt(t,e){let r=t.indexOf(e);return r!==-1?t[r+1]:void 0}if(D==="--version"||D==="-v"){let{version:t}=ae();process.stdout.write(t+`
|
|
208
|
+
`),process.exit(0);}else if(D==="--help"||D==="-h"){let{bold:t,cyan:e,dim:r}=(it(),P(Ne)),{version:n}=ae();process.stdout.write(`
|
|
206
209
|
`+t(" flow-ai-obs")+r(" v"+n)+`
|
|
207
210
|
|
|
208
211
|
`),process.stdout.write(e(" init")+r(` Auth (if needed) + hooks + native OTEL
|
|
@@ -222,13 +225,13 @@ ${r}`},{re:/\b(AKIA[0-9A-Z]{16})\b/g,replace:()=>`AKIA${F}`},{re:/(aws_secret_ac
|
|
|
222
225
|
|
|
223
226
|
`)),process.stdout.write(r(` (Hook events: UserPromptSubmit | PreToolUse | PostToolUse | Stop)
|
|
224
227
|
|
|
225
|
-
`)),process.exit(0);}else if(
|
|
226
|
-
`),await(At(),P(
|
|
227
|
-
`),process.exit(1);});else if(
|
|
228
|
-
`),process.exit(1);});else if(
|
|
228
|
+
`)),process.exit(0);}else if(D==="init"||D==="install")(async()=>{D==="install"&&process.stderr.write(`Warning: "install" is deprecated, use "init" instead
|
|
229
|
+
`),await(At(),P(Ot)).checkForUpdateInteractive();let{runInit:t}=(lr(),P(cr)),e=process.argv.slice(3);process.exit(await t({url:rt(e,"--custom-url"),noInteractive:e.includes("--no-interactive")}));})().catch(t=>{process.stderr.write(`Unexpected error: ${t.message}
|
|
230
|
+
`),process.exit(1);});else if(D==="setup")(async()=>{await(At(),P(Ot)).checkForUpdateInteractive();let{runSetup:t}=(wn(),P(En)),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}
|
|
231
|
+
`),process.exit(1);});else if(D==="auth")(async()=>{let{runLogin:t,runLogout:e,runStatus:r}=(zt(),P(ir)),n=0;if(re==="login"||!re){await(At(),P(Ot)).checkForUpdateInteractive();let s=process.argv.slice(4);n=await t({clientId:rt(s,"--client-id"),clientSecret:rt(s,"--client-secret"),tenant:rt(s,"--tenant")});}else if(re==="logout"){let s=process.argv.includes("--force");n=await e(s);}else re==="status"?(await(At(),P(Ot)).checkForUpdateInteractive(),n=await r()):(process.stderr.write(`Unknown auth subcommand: ${re}
|
|
229
232
|
`),process.stderr.write(`Usage: flow-ai-obs auth [login|logout|status]
|
|
230
|
-
`),n=1);process.exit(n);})();else if(
|
|
231
|
-
`),process.exit(1);});else if(
|
|
233
|
+
`),n=1);process.exit(n);})();else if(D==="otel-headers"){let{runOtelHeaders:t}=(Tn(),P(Sn));t().then(e=>process.exit(e)).catch(()=>process.exit(1));}else if(D==="check")(async()=>{await(At(),P(Ot)).checkForUpdateInteractive();let{runCheck:t}=(On(),P(_n));process.exit(await t());})().catch(t=>{process.stderr.write(`Unexpected error: ${t.message}
|
|
234
|
+
`),process.exit(1);});else if(li.has(D))is();else {let{bold:t,cyan:e,dim:r}=(it(),P(Ne));process.stdout.write(`
|
|
232
235
|
`+t(" flow-ai-obs")+`
|
|
233
236
|
|
|
234
237
|
`),process.stdout.write(e(" init")+r(` Auth (if needed) + hooks + native OTEL
|
package/dist/index.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
'use strict';var child_process=require('child_process'),util=require('util'),
|
|
2
|
-
`;try{
|
|
3
|
-
`);}}var b=class extends Error{constructor(e){super(e),this.name="AuthError";}},
|
|
4
|
-
`)[0].slice(0,e).trim()}function
|
|
5
|
-
`);for(let r=e.length-1;r>=0;r--)try{let n=JSON.parse(e[r]);if(n.type==="user"&&n.uuid)return n.uuid}catch{}}catch{}return null}function
|
|
6
|
-
`),r=[],n=0,
|
|
1
|
+
'use strict';var child_process=require('child_process'),util=require('util'),R=require('fs'),_e=require('os'),x=require('path'),ze=require('https'),Xe=require('http'),crypto=require('crypto');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var R__default=/*#__PURE__*/_interopDefault(R);var _e__default=/*#__PURE__*/_interopDefault(_e);var x__default=/*#__PURE__*/_interopDefault(x);var ze__default=/*#__PURE__*/_interopDefault(ze);var Xe__default=/*#__PURE__*/_interopDefault(Xe);var ve=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)ve(t,r,{get:e[r],enumerable:true});};var Dt={};ft(Dt,{MacOsKeyVaultProvider:()=>Tt});var St,Tt,xt=dt(()=>{"use strict";St=util.promisify(child_process.execFile),Tt=class{static async isAvailable(){try{return R.accessSync("/usr/bin/security",R.constants.X_OK),!0}catch{return !1}}async getSecret(e,r){try{let{stdout:n}=await St("security",["find-generic-password","-w","-a",r,"-s",e]);return n.trim()||null}catch{return null}}async setSecret(e,r,n){await St("security",["add-generic-password","-U","-a",r,"-s",e,"-w",n]);}async deleteSecret(e,r){try{return await St("security",["delete-generic-password","-a",r,"-s",e]),!0}catch{return !1}}getStoragePath(){return "macOS Keychain"}};});var Bt={};ft(Bt,{LinuxKeyVaultProvider:()=>ht});var Mt,ht,Ht=dt(()=>{"use strict";Mt=util.promisify(child_process.execFile),ht=class{static async isAvailable(){let e=["/usr/bin/secret-tool","/bin/secret-tool","/usr/local/bin/secret-tool"];for(let r of e)try{return R.accessSync(r,R.constants.X_OK),!0}catch{}return !1}async getSecret(e,r){try{let{stdout:n}=await Mt("secret-tool",["lookup","service",e,"account",r]);return n.trim()||null}catch{return null}}async setSecret(e,r,n){await new Promise((o,s)=>{let i=child_process.spawn("secret-tool",["store","--label",e,"service",e,"account",r]);i.on("error",s),i.on("close",l=>{l===0?o():s(new Error(`secret-tool exited with code ${l}`));}),i.stdin.write(n),i.stdin.end();});}async deleteSecret(e,r){try{return await Mt("secret-tool",["clear","service",e,"account",r]),!0}catch{return !1}}getStoragePath(){return "Linux Secret Service (libsecret)"}};});var Wt={};ft(Wt,{WindowsKeyVaultProvider:()=>At});var At,Vt=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 Ue="https://flow.ciandt.com";function D(){let t=process.env.FLOW_BASE_URL;return t&&t.trim()?t.trim():Ue}function Y(){let t=D();return {AUTH_ENGINE:process.env.FLOW_AUTH_ENGINE_URL||`${t}/auth-engine-api/v2/api-key/token`,GATEWAY_TRACES:process.env.FLOW_GATEWAY_TRACES_URL||`${t}/flow-langfuse-gateway/v1/traces`,GATEWAY_HEALTH:process.env.FLOW_GATEWAY_HEALTH_URL||`${t}/flow-langfuse-gateway/v1/health`,OTEL_ENDPOINT:process.env.FLOW_OTEL_ENDPOINT_URL||`${t}/otel`}}Y();var rt={SERVICE:"flow-plugins-cli",ACCOUNT_TOKEN:"token-cache"},nt="FLOW-nodejs",st="config.json",mt={SCOPE_NAME:"flow-ai-obs",SCOPE_VERSION:"0.1.0"};var E={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 y={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},$t="flow-ai-obs-debug.log",w={TOOL_INPUT:2e4,TOOL_OUTPUT:2e4,TRACE_OUTPUT:2e4,USER_INSTRUCTION:1e4,TRACE_INPUT:5e4};function gt(){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 _t(){try{let t=R__default.default.readFileSync(G(),"utf8");return JSON.parse(t)}catch{return {}}}function Ft(t){let e=G();R__default.default.mkdirSync(x__default.default.dirname(e),{recursive:true}),R__default.default.writeFileSync(e,JSON.stringify(t,null,2),{encoding:"utf8",mode:384});}var ot=class{static isAvailable(){return true}static hasExistingData(){try{if(!R__default.default.existsSync(G()))return !1;let e=JSON.parse(R__default.default.readFileSync(G(),"utf8"));return !!(e&&e.credentials)}catch{return false}}async getSecret(e,r){let n=_t(),o=Et[r]??r,s=n[o];return s?typeof s=="string"?s:JSON.stringify(s):null}async setSecret(e,r,n){let o=_t(),s=Et[r]??r;if(r==="token-cache")try{o[s]=JSON.parse(n);}catch{o[s]=n;}else o[s]=n;Ft(o);}async deleteSecret(e,r){let n=_t(),o=Et[r]??r;return o in n?(delete n[o],Ft(n),true):false}getStoragePath(){return `config.json (unencrypted) \u2014 ${G()}`}};async function Yt(){return await Ge()??new ot}async function Ge(){switch(process.platform){case "darwin":{let{MacOsKeyVaultProvider:t}=await Promise.resolve().then(()=>(xt(),Dt));return await t.isAvailable()?new t:null}case "linux":{let{LinuxKeyVaultProvider:t}=await Promise.resolve().then(()=>(Ht(),Bt));return await t.isAvailable()?new t:null}case "win32":{let{WindowsKeyVaultProvider:t}=await Promise.resolve().then(()=>(Vt(),Wt));return await t.isAvailable()?new t:null}default:return null}}var Gt=rt.SERVICE,Jt=rt.ACCOUNT_TOKEN,yt=null;function Kt(){return yt||(yt=Yt()),yt}async function Ot(t){await(await Kt()).setSecret(Gt,Jt,JSON.stringify({accessToken:t.accessToken,expiresAt:t.expiresAt,lastAuthCheckAt:t.lastAuthCheckAt}));}async function wt(){let e=await(await Kt()).getSecret(Gt,Jt);if(!e)return null;try{let r=JSON.parse(e);return {accessToken:r.accessToken,expiresAt:r.expiresAt,lastAuthCheckAt:r.lastAuthCheckAt}}catch{return null}}async function kt(){let t=await wt();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 qe=x.join(_e.tmpdir(),$t);function a(...t){if(process.env[E.FLOW_OBS_DEBUG]!=="1")return;let e=`[${new Date().toISOString()}] ${t.join(" ")}
|
|
2
|
+
`;try{R.writeFileSync(qe,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";}},Ze=/^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$|^[a-z0-9]$/;function Qe(t){if(!Ze.test(t))throw new Error(`Invalid tenant value: "${t}". Tenant must be lowercase alphanumeric and hyphens (1-64 chars).`)}var jt={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 tr(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}`:"")),jt[n.error]))return new b(jt[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{Qe(t.tenant);}catch(p){return r(p)}let n=JSON.stringify({clientSecret:t.clientSecret}),o=new URL(Y().AUTH_ENGINE),s=o.protocol==="https:",i={hostname:o.hostname,port:o.port||(s?443:80),path:o.pathname+o.search,method:"POST",headers:{"Content-Type":"application/json","Content-Length":Buffer.byteLength(n),FlowTenant:t.tenant}};a("getToken",`requesting token tenant=${t.tenant} host=${i.hostname} path=${i.path}`);let c=(s?ze__default.default:Xe__default.default).request(i,p=>{let _=[];p.on("data",S=>_.push(S)),p.on("end",()=>{let S=_.join("");if((p.statusCode??0)>=400)return r(tr(p.statusCode??0,S));let d;try{d=JSON.parse(S);}catch{return r(new Error("Invalid response from auth engine"))}let g=d.expires_at??new Date(Date.now()+(d.expires_in??3600)*1e3).toISOString();e({accessToken:d.access_token??"",expiresAt:g});});});c.on("error",p=>r(new Error(`Network error: ${p.message}`))),c.write(n),c.end();})}var rr=[/^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 nr(t){return rr.some(e=>e.test(t))}function sr(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:o,tenant:s}=r;return !n||!o||!s?null:{clientId:n,clientSecret:o,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[E.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&&nr(e.hostname))throw new Error(`SSRF: private/loopback host not allowed: ${e.hostname}`);return t}async function Xt(){let t=at(process.env[E.ANTHROPIC_AUTH_TOKEN]);return t?{user:await kt().catch(()=>null)??t.clientId,tenant:t.tenant}:{user:"",tenant:""}}function or(){return new Date().toISOString().slice(0,10)}async function ir(t){let e=or(),r=await wt();if(r?.lastAuthCheckAt!==e){a("getOrRefreshToken",`daily auth check (last: ${r?.lastAuthCheckAt??"never"})`);try{let s=await K(t);try{await Ot({...s,lastAuthCheckAt:e});}catch{}return a("getOrRefreshToken",`daily check passed, expires=${s.expiresAt}`),s.accessToken}catch(s){if(s instanceof b)throw s;a("getOrRefreshToken",`daily check network error \u2014 using cache: ${s.message}`);}}let n=r!=null&&new Date(r.expiresAt)>new Date;if(a("getOrRefreshToken",`cacheValid=${n}`),n)return a("getOrRefreshToken",`using cached token, expires=${r.expiresAt}`),r.accessToken;a("getOrRefreshToken",`token expired \u2014 refreshing via auth-engine (tenant=${t.tenant} clientId=${t.clientId})`);let o=await K(t);try{await Ot({...o,lastAuthCheckAt:e});}catch(s){a("getOrRefreshToken",`token cache save failed (non-fatal): ${s.message}`);}return a("getOrRefreshToken",`token refreshed, expires=${o.expiresAt}`),o.accessToken}function ar(t,e){let r=e&&e.accessToken?e.accessToken:"";return {endpoint:t.replace(/\/$/,"")+"/flow-langfuse-gateway/v1/traces",authHeader:`Bearer ${r}`}}function cr(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[E.ANTHROPIC_MODEL]??"",r=at(process.env[E.ANTHROPIC_AUTH_TOKEN]);a("resolveCredentials",r?"credentials resolved from ANTHROPIC_AUTH_TOKEN":"ANTHROPIC_AUTH_TOKEN absent or invalid"),r&&a("resolveCredentials",`clientId=${r.clientId}`,`tenant=${r.tenant}`);let n=r?r.tenant:"",o=process.env[E.FLOW_TELEMETRY]==="true",s=process.env[E.LANGFUSE_BASE_URL],i=process.env[E.LANGFUSE_PUBLIC_KEY],l=process.env[E.LANGFUSE_SECRET_KEY];if(o&&s&&i&&l){let d="",g=n;r&&(d=await kt().catch(()=>null)??r.clientId);let T={user:d??"",tenant:g??"",team:"",project:"",model:e};t.push({mode:"direct",...cr(it(s),i,l),...T}),a("resolveCredentials","direct mode active",`user=${T.user}`,`tenant=${T.tenant}`);}if(!r){if(t.length===0){let d=[];return d.authError=false,d}return t}let c;try{c=await ir(r);}catch(d){if(a("resolveCredentials",`token refresh failed: ${d.message}`,`(tenant=${r.tenant} clientId=${r.clientId})`),t.length>0)return t.authError=true,t;let g=[];return g.authError=true,g}let _={user:sr(c)??r.clientId,tenant:n,team:"",project:"",model:e},S=process.env[E.FLOW_TELEMETRY_GATEWAY]??D();return t.push({mode:"gateway",...ar(it(S),{accessToken:c}),..._}),t}async function Zt(){return (await v()).length>0}var qt=false,zt=false;function Qt(){let t=process.env[E.FLOW_USER_EMAIL];if(t)return a("resolveUserEmail","using FLOW_USER_EMAIL override: [REDACTED]"),t.replace(/[\r\n]/g,"").trim();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"),qt||(qt=!0,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: [REDACTED]"),n}catch(e){return a("resolveUserEmail",`os.userInfo() threw: ${e.message} \u2014 omitting x-flow-user`),zt||(zt=true,console.warn("[flow-ai-obs] Could not derive x-flow-user from OS username. Set FLOW_USER_EMAIL to fix this.")),null}}function te(){let t=process.env.OTEL_EXPORTER_OTLP_HEADERS;return t?t.replace(/[\r\n]/g,"").trim():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 Lt(){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,Sr=x.normalize(_e.tmpdir())+x.sep;function Tr(t,e){let r=x.resolve(t);if(!r.startsWith(e))throw new Error(`Path traversal detected: ${t}`);return r}function It(t){if(!_r.test(t))throw new Error(`Invalid session ID: ${t}`);return Tr(x.join(_e.tmpdir(),`flow-obs-${t}.json`),Sr)}function M(t){let e=It(t);if(!R.existsSync(e))return null;try{return JSON.parse(R.readFileSync(e,"utf8"))}catch{return null}}function B(t,e){R.writeFileSync(It(t),JSON.stringify(e),{encoding:"utf8",mode:384});}function Pt(t){try{R.unlinkSync(It(t));}catch{}}function oe(t){if(!t||!R.existsSync(t))return null;try{let e=R.readFileSync(t,"utf8").trimEnd().split(`
|
|
5
|
+
`);for(let r=e.length-1;r>=0;r--)try{let n=JSON.parse(e[r]);if(n.type==="user"&&n.uuid)return n.uuid}catch{}}catch{}return null}function Nt(t){if(!t||!R.existsSync(t))return null;try{let e=R.readFileSync(t,"utf8").trimEnd().split(`
|
|
6
|
+
`),r=[],n=0,o=0;for(let s=e.length-1;s>=0;s--)try{let i=JSON.parse(e[s]);if(i.type==="user")break;if(i.type==="assistant"){let c=(i.message?.content??[]).filter(_=>_.type==="text").map(_=>_.text??"").join("");c&&r.unshift(c);let p=i.message?.usage??{};n+=(p.input_tokens??0)+(p.cache_read_input_tokens??0)+(p.cache_creation_input_tokens??0),o+=p.output_tokens??0;}}catch{}return !r.length&&n===0?null:{text:r.join(`
|
|
7
7
|
|
|
8
|
-
`),inputTokens:n,outputTokens:
|
|
9
|
-
`)[0].match(/^\/([a-z][a-z0-9-]*(?::[a-z][a-z0-9-]*)?)(?:\s.*)?$/i)?.[1]??null}var
|
|
10
|
-
`);return}let n=!!(await v()).authError,
|
|
11
|
-
`,{flag:"a",encoding:"utf8",mode:384}),a("sendTraces:dump",`request appendada em ${
|
|
12
|
-
${
|
|
13
|
-
${r}`},{re:/\b(AKIA[0-9A-Z]{16})\b/g,replace:()=>`AKIA${
|
|
14
|
-
`)),T=p?.inputTokens??0,h=p?.outputTokens??0,q=
|
|
15
|
-
`),process.stdout.write(JSON.stringify(e));}}
|
|
8
|
+
`),inputTokens:n,outputTokens:o}}catch{}return null}var Or=new Set([".venv","__pycache__",".git","node_modules"]),wr=new Set([".pyc",".pyo"]),kr=new Set(["SKILL.md",".DS_Store",".gitignore"]);function ce(t){return t.replace(":","/")}function lt(t,e){if(!t)return null;let r=ce(t),n=[x.join(_e.homedir(),".claude","skills",r,"SKILL.md"),x.join(e??"",".claude","skills",r,"SKILL.md")];for(let o of n)if(R.existsSync(o))try{return R.readFileSync(o,"utf8")}catch{}return null}function le(t){return t.split(`
|
|
9
|
+
`)[0].match(/^\/([a-z][a-z0-9-]*(?::[a-z][a-z0-9-]*)?)(?:\s.*)?$/i)?.[1]??null}var Lr=new Set(["Read","Write","Edit","MultiEdit","Bash","Glob","Grep","TodoWrite","WebFetch","WebSearch","Agent","Task"]);function ue(t){return !!t.slashSkill||t.toolCalls.some(n=>n.tool==="Skill")?t.toolCalls.some(n=>n.tool==="Skill"&&!n.synthetic||Lr.has(n.tool))?"complete":"prerequisite_required":null}function ut(t,e){if(!t)return null;let r=ce(t),n=[x.join(_e.homedir(),".claude","skills",r),x.join(e??"",".claude","skills",r)],o=null;for(let l of n)if(R.existsSync(x.join(l,"SKILL.md"))){o=l;break}if(!o)return null;let s=[];function i(l,c){for(let p of R.readdirSync(l,{withFileTypes:true})){if(Or.has(p.name)||kr.has(p.name)||wr.has(x.extname(p.name)))continue;let _=c?`${c}/${p.name}`:p.name;p.isDirectory()?i(x.join(l,p.name),_):s.push(_);}}return i(o,""),s.length>0?s:null}function Pr(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(o=>{let s=new URL(t),i=s.protocol==="https:",l=(i?ze__default.default:Xe__default.default).request({hostname:s.hostname,port:s.port||(i?443:80),path:s.pathname+s.search,method:"POST",headers:{"Content-Type":"application/json","Content-Length":Buffer.byteLength(e),Authorization:`Bearer ${String(r).replace(/[\r\n]/g,"")}`,FlowTenant:String(n).replace(/[\r\n]/g,"")}},c=>{c.resume(),o(c.statusCode??0);});l.on("error",()=>o(0)),l.setTimeout(5e3,()=>{l.destroy(),o(0);}),l.write(e),l.end();})}async function C(t,e={}){try{let r=at(process.env[E.ANTHROPIC_AUTH_TOKEN]);if(!r)return;let n,o=new Promise((S,d)=>{n=setTimeout(()=>d(new Error("getToken timeout")),4e3),n.unref();}),{accessToken:s}=await Promise.race([K(r),o]);clearTimeout(n);let i=Pr(s);if(!i)return;let l=i.tenant||r.tenant,c=JSON.stringify({action:t,booster:gt().BOOSTER,metadata:e,success:!0,tenant:l,timestamp:new Date().toISOString(),os:process.platform,user:{email:i.email||"",id:i.sub||"",name:i.name||i.email||""}}),p=it(gt().API_URL),_=await Nr(p,c,s,l);a("metrics.logEvent",`action=${t} status=${_}`);}catch(r){a("metrics.logEvent",`silenced error: ${r.message}`);}}var br=`\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 bt(t,e=false){if(e){process.stdout.write(JSON.stringify({decision:"block",reason:br})+`
|
|
10
|
+
`);return}let n=!!(await v()).authError,o=t.session_id||"unknown",s=t.prompt||"",i=t.cwd||"",l=oe(t.transcript_path)||Rt(),c=le(s),p=c?lt(c,i):null,_=c?ut(c,i):null;B(o,{traceId:Rt(),spanId:U(),startNs:L(),sessionId:o,prompt:s,cwd:i,traceName:l,transcriptPath:t.transcript_path||"",model:process.env[E.ANTHROPIC_MODEL]||"",toolCalls:[],spans:[],pendingTool:null,slashSkill:c,skillContent:p,skillArtifacts:_}),C("SESSION_STARTED",{traceType:c?"skill":"prompt",slashSkill:c,clientIdExpired:n}),a("UserPromptSubmit",`sid=${o}`,`traceName=${l}`,`slashSkill=${c}`),O(t);}async function pe(t){let e=t.session_id||"unknown",r=t.tool_name||"unknown",n=t.tool_input||{},o=M(e);o&&(o.pendingTool={name:r,inputStr:k(n,w.TOOL_INPUT),startNs:L()},B(e,o)),a("PreToolUse",`sid=${e}`,`tool=${r}`,`stateFound=${!!o}`),O(t);}var vr={name:mt.SCOPE_NAME,version:mt.SCOPE_VERSION},m={TRACE_NAME:"langfuse.trace.name",TRACE_INPUT:"langfuse.trace.input",TRACE_OUTPUT:"langfuse.trace.output",TRACE_METADATA:"langfuse.trace.metadata",TRACE_TAGS:"langfuse.trace.tags",USER_ID:"langfuse.user.id",SESSION_ID:"langfuse.session.id",OBS_NAME:"langfuse.observation.name",OBS_INPUT:"langfuse.observation.input",OBS_OUTPUT:"langfuse.observation.output",OBS_LEVEL:"langfuse.observation.level",OBS_TYPE:"langfuse.observation.type",MODEL:"gen_ai.request.model",INPUT_TOKENS:"gen_ai.usage.input_tokens",OUTPUT_TOKENS:"gen_ai.usage.output_tokens"};function u(t,e){return e==null||e===""?null:{key:t,value:{stringValue:String(e)}}}function $(...t){return t.filter(e=>e!==null)}function de(t,e){return {resourceSpans:[{resource:{attributes:t},scopeSpans:[{scope:vr,spans:Array.isArray(e)?e:[e]}]}]}}var fe=x.join(_e.tmpdir(),"flow-obs-requests.ndjson");function me(t,e,r,n,o){if(process.env[E.FLOW_OBS_DEBUG]!=="1")return;let s={...e};"Authorization"in s&&(s.Authorization="[REDACTED]"),"x-flow-user"in s&&(s["x-flow-user"]="[REDACTED]"),"x-flow-api-key"in s&&(s["x-flow-api-key"]="[REDACTED]");let i=JSON.stringify({ts:new Date().toISOString(),request:{method:"POST",url:t,headers:s,body:JSON.parse(r)},response:{status:n,body:o}});try{R.writeFileSync(fe,i+`
|
|
11
|
+
`,{flag:"a",encoding:"utf8",mode:384}),a("sendTraces:dump",`request appendada em ${fe}`);}catch(l){a("sendTraces:dump",`falha ao salvar: ${l.message}`);}}function xr(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 ge(t,e){return new Promise((r,n)=>{let o=t._isSSL?ze__default.default:Xe__default.default;t.headers=Object.assign({},t.headers,{Connection:"close"});let s=o.request(t,i=>{let l=[];i.on("data",c=>l.push(c)),i.on("end",()=>r({statusCode:i.statusCode??0,body:l.join("")}));});s.setTimeout(1e4,()=>{s.destroy(new Error("Request timeout"));}),s.on("error",i=>n(new Error(`Network error: ${i.message}`))),e&&s.write(e),s.end();})}async function Ee(t,e){let r;try{r=xr(t);}catch{return false}let n=r.protocol==="https:";try{let o={};e&&(o.Authorization=String(e).replace(/[\r\n]/g,""));let s=await ge({hostname:r.hostname,port:r.port||(n?443:80),path:r.pathname,method:"GET",headers:o,_isSSL:n},null);return a("checkHealth",`url=${r.href} status=${s.statusCode}`),s.statusCode>=200&&s.statusCode<300}catch{return false}}async function pt(t,e,r){let n=JSON.stringify(t),o=new URL(e),s=o.protocol==="https:",i=String(r).replace(/[\r\n]/g,""),l=d=>d.replace(/[\r\n]/g,""),c=Qt(),p=te(),_={...c?{"x-flow-user":l(c)}:{},...p?{"x-flow-api-key":l(p)}:{}},S={"Content-Type":"application/json",Authorization:i,"Content-Length":Buffer.byteLength(n),..._};a("sendTraces:request",`POST ${e}`),a("sendTraces:request",`headers=${JSON.stringify({...S,Authorization:i.slice(0,20)+"\u2026","x-flow-user":c?"[REDACTED]":void 0,"x-flow-api-key":p?"[REDACTED]":void 0})}`),a("sendTraces:request",`body=${n.slice(0,500)}${n.length>500?"\u2026":""}`);try{let d=await ge({hostname:o.hostname,port:o.port||(s?443:80),path:o.pathname,method:"POST",headers:S,_isSSL:s},n);return a("sendTraces:response",`status=${d.statusCode}`),me(e,S,n,d.statusCode,d.body),d.statusCode}catch(d){return a("sendTraces:error",d.message),me(e,S,n,0,d.message),0}}function Mr(){let t=parseInt(process.env[E.BUFFER_TTL_DAYS]??"",10);return (Number.isFinite(t)?Math.max(y.MIN_TTL_DAYS,Math.min(y.MAX_TTL_DAYS,t)):y.DEFAULT_TTL_DAYS)*24*60*60*1e3}function Br(){let t=parseInt(process.env[E.BUFFER_MAX_FILES]??"",10);return Number.isFinite(t)?Math.max(y.MIN_MAX_FILES,Math.min(y.MAX_MAX_FILES,t)):y.DEFAULT_MAX_FILES}function Se(t){if(/[/\\]/.test(t))throw new Error(`Invalid buffer fileId: ${t}`);return x__default.default.join(_e__default.default.tmpdir(),`${y.FILE_PREFIX}${t}.json`)}function Ut(){let t=_e__default.default.tmpdir(),e;try{e=R__default.default.readdirSync(t);}catch{return []}return e.filter(r=>r.startsWith(y.FILE_PREFIX)&&r.endsWith(".json")).map(r=>{let n=x__default.default.join(t,r),o=0;try{o=R__default.default.statSync(n).mtimeMs;}catch{}return {full:n,mtime:o}}).sort((r,n)=>r.mtime-n.mtime).map(r=>r.full)}function j(t){try{let e=Br(),r=Ut();if(r.length>=e){let s=r.slice(0,r.length-e+1);for(let i of s)try{R__default.default.unlinkSync(i);}catch{}}let n=`${Date.now()}-${Math.random().toString(36).slice(2,8)}`,o={fileId:n,bufferedAt:Date.now(),payload:t};return R__default.default.writeFileSync(Se(n),JSON.stringify(o),{encoding:"utf8",mode:384}),a("buffer",`saved fileId=${n}`),n}catch(e){return a("buffer",`saveToBuffer failed: ${e.message}`),null}}function Te(t){let e=Ut(),r=t,n=[];for(let o of e){if(n.length>=r)break;try{let s=R__default.default.readFileSync(o,"utf8"),i=JSON.parse(s);i&&i.fileId&&i.payload&&n.push(i);}catch{a("buffer",`skipping malformed file: ${o}`);}}return n}function he(t){try{R__default.default.unlinkSync(Se(t)),a("buffer",`deleted fileId=${t}`);}catch{}}function Ae(){let t=Date.now()-Mr();for(let e of Ut())try{let{mtimeMs:r}=R__default.default.statSync(e);r<t&&(R__default.default.unlinkSync(e),a("buffer",`evicted stale: ${x__default.default.basename(e)}`));}catch{}}async function Hr(t){Ae();let e=Te(y.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,t.authHeader);n>=200&&n<300?(he(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 i=await Ee(s.endpoint,s.authHeader);return {creds:s,healthy:i}})),n=r.find(s=>s.creds.mode==="gateway"&&s.healthy)?.creds??r.find(s=>s.creds.mode==="direct")?.creds;return n&&await Hr(n),(await Promise.all(r.map(async({creds:s,healthy:i})=>{if(s.mode==="gateway"){if(!i)return a("postToLangfuse","gateway health check failed \u2014 buffering trace"),j(t),0;let c=await pt(t,s.endpoint,s.authHeader);return (c===0||c>=500)&&(a("postToLangfuse",`gateway send failed (status ${c}) \u2014 buffering trace`),j(t)),c}let l=await pt(t,s.endpoint,s.authHeader);return (l===0||l>=500)&&(a("postToLangfuse",`direct endpoint unavailable (status ${l}) \u2014 buffering trace`),j(t)),l}))).find(s=>s!==0)??0}var A="[REDACTED]",Wr="[REDACTED-EMAIL]",Vr="[REDACTED-CPF]",Yr="[REDACTED-CNPJ]",Oe="[REDACTED-PHONE]",Gr=[{re:/\b(sk-[A-Za-z0-9_\-]{20,})/g,replace:()=>`sk-${A}`},{re:/\b(pk-[A-Za-z0-9_\-]{20,})/g,replace:()=>`pk-${A}`},{re:/\b(Bearer\s+)[A-Za-z0-9\-._~+/]+=*/gi,replace:(t,e)=>`${e}${A}`},{re:/\b(Basic\s+)[A-Za-z0-9+/]+=*/gi,replace:(t,e)=>`${e}${A}`},{re:/(-----BEGIN [A-Z ]+-----)[^-]*(-----END [A-Z ]+-----)/g,replace:(t,e,r)=>`${e}
|
|
12
|
+
${A}
|
|
13
|
+
${r}`},{re:/\b(AKIA[0-9A-Z]{16})\b/g,replace:()=>`AKIA${A}`},{re:/(aws_secret_access_key\s*[=:]\s*)([A-Za-z0-9/+]{40})/gi,replace:(t,e)=>`${e}${A}`},{re:/\b(ghp_[A-Za-z0-9]{36,})/g,replace:()=>`ghp_${A}`},{re:/\b(github_pat_[A-Za-z0-9_]{36,})/gi,replace:()=>`github_pat_${A}`},{re:/\b(eyJ[A-Za-z0-9_\-]+\.eyJ[A-Za-z0-9_\-]+\.[A-Za-z0-9_\-]+)/g,replace:()=>`eyJ.${A}`},{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}${A}${r}`},{re:/([a-z][a-z0-9+\-.]*:\/\/[^:/?#\s]*):([^@\s]+)@/gi,replace:(t,e)=>`${e}:${A}@`},{re:/[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}/g,replace:()=>Wr},{re:/\b\d{3}\.\d{3}\.\d{3}-\d{2}\b/g,replace:()=>Vr},{re:/\b\d{2}\.\d{3}\.\d{3}\/\d{4}-\d{2}\b/g,replace:()=>Yr},{re:/\(\d{2}\)\s?\d{4,5}[-\s]?\d{4}/g,replace:()=>Oe},{re:/\+55[\s-]?\d{2}[\s-]?\d{4,5}[-\s]?\d{4}/g,replace:()=>Oe}];function I(t){if(t==null)return "";let e=typeof t=="string"?t:JSON.stringify(t);return Gr.reduce((r,{re:n,replace:o})=>r.replace(n,o),e)}async function we(t){let e=t.session_id||"unknown",r=t.tool_name||"unknown",n=t.tool_input||{},o=t.tool_response,s=o!==null&&typeof o=="object"?o.output??JSON.stringify(o):o??"",i=M(e);if(!i){O(t);return}let l=L(),c=i.pendingTool,p=c?.name===r,_=p?c.startNs:String(BigInt(l)-200000000n),S=p?c.inputStr:k(n,w.TOOL_INPUT),d=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 P=g?lt(g,i.cwd):null;P&&(d=P,i.skillContent||(i.skillContent=P),i.skillArtifacts||(i.skillArtifacts=ut(g,i.cwd))),g&&!i.slashSkill&&(i.slashSkill=g),a("PostToolUse","Skill tool detected",`skillName=${g}`,`contentFound=${!!P}`);}let T=I(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(),z=Math.round(Number(BigInt(l)-BigInt(_))/1e6),Z={Agent:"AGENT",Task:"AGENT"}[r]??"TOOL",Q=r==="Skill"&&g?g:ct(S,60);i.toolCalls.push({tool:r,brief:Q,error:h,durationMs:z});let V=i.spans;V.push({traceId:i.traceId,spanId:W,parentSpanId:i.spanId,name:r,kind:3,startTimeUnixNano:_,endTimeUnixNano:l,attributes:$(u(m.OBS_NAME,r),u(m.OBS_TYPE,Z),u(m.OBS_LEVEL,q),u(m.OBS_INPUT,I(d)),u(m.OBS_OUTPUT,T),u("tool.name",r),u("tool.error",String(h)),r==="Skill"&&g?u("skill.name",g):null,r==="Skill"?u("skill.invocation","slash-command"):null),status:{code:h?2:1}}),i.pendingTool=null,B(e,i),h&&C("TOOL_ERROR",{toolName:r}),a("PostToolUse",`sid=${e}`,`tool=${r}`,`error=${h}`,`durationMs=${z}`,`totalSpans=${V.length}`),O(t);}var ke={"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 Le(t,e,r){let n=Object.keys(ke).find(i=>(t??"").toLowerCase().includes(i));if(!n)return;let o=ke[n],s=(e*o.input+r*o.output)/1e6;return Math.round(s*1e6)/1e6}async function Re(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 o=L(),s=await Xt(),i=n.toolCalls,l=n.spans;if(n.slashSkill&&!i.some(f=>f.tool==="Skill")){let f=U(),N=n.skillContent?n.skillContent:JSON.stringify({skill:n.slashSkill});i.push({tool:"Skill",brief:n.slashSkill,error:false,durationMs:0,synthetic:true}),l.push({traceId:n.traceId,spanId:f,parentSpanId:n.spanId,name:"Skill",kind:3,startTimeUnixNano:n.startNs,endTimeUnixNano:n.startNs,attributes:$(u(m.OBS_NAME,"Skill"),u(m.OBS_TYPE,"TOOL"),u(m.OBS_LEVEL,"DEFAULT"),u(m.OBS_INPUT,N),u(m.OBS_OUTPUT,"loaded via slash command"),u("tool.name","Skill"),u("tool.error","false"),u("skill.name",n.slashSkill),u("skill.invocation","slash-command")),status:{code:1}}),a("Stop",`slashSkill=${n.slashSkill}`,"synthetic span injected");}let c=t.transcript_path||n.transcriptPath||"",p=Nt(c);if(c&&(i.some(f=>f.tool==="Skill"&&!f.synthetic)||!!n.slashSkill)&&!p?.text){await new Promise(N=>setTimeout(N,500));let f=Nt(c);f?.text&&(p=f);}a("Stop",`transcriptPath=${c||"(empty)"}`,`assistantOut=${p?`text=${p.text.length}chars`:"null"}`);let S=i.length,d=i.filter(f=>f.error).length,g=I(p?.text?k(p.text,w.TRACE_OUTPUT):S===0?"No tools used":i.map((f,N)=>`${N+1}. ${f.tool}${f.brief?` \u2192 ${f.brief}`:""}${f.error?" [ERROR]":""}`).join(`
|
|
14
|
+
`)),T=p?.inputTokens??0,h=p?.outputTokens??0,q=i.map((f,N)=>`${N+1}. ${f.tool}${f.brief?` \u2192 ${f.brief}`:""}${f.error?" [ERROR]":""} (${f.durationMs}ms)`),W=!!(n.slashSkill||i.some(f=>f.tool==="Skill")),z=i.some(f=>f.tool==="Agent");if(!W&&!z){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 X=W?"skill":"agent",Z=Math.round(Number(BigInt(o)-BigInt(n.startNs))/1e6),Q=Le(n.model,T,h),F=ue(n);F==="prerequisite_required"&&p?.text&&(F="complete"),F==="prerequisite_required"&&(l.push({traceId:n.traceId,spanId:U(),parentSpanId:n.spanId,name:"prerequisite-check",kind:3,startTimeUnixNano:n.startNs,endTimeUnixNano:o,attributes:$(u(m.OBS_NAME,"prerequisite-check"),u(m.OBS_TYPE,"EVENT"),u(m.OBS_LEVEL,"WARNING"),u(m.OBS_OUTPUT,g),u("skill.name",n.slashSkill||void 0),u("execution_status","prerequisite_required")),status:{code:1}}),a("Stop",`sid=${e}`,"prerequisite-check span injected",`skill=${n.slashSkill}`));let V=(()=>{if(!(!W||!n.prompt)){if(n.slashSkill){let f=n.prompt.replace(new RegExp(`^\\/${n.slashSkill}\\s*`,"i"),"").trim();return f?k(I(f),w.USER_INSTRUCTION):void 0}return k(I(n.prompt),w.USER_INSTRUCTION)||void 0}})(),tt=JSON.stringify({trace_type:X,...F!==null&&{execution_status:F},...n.slashSkill?{skill_name:n.slashSkill}:{},...n.skillArtifacts?.length&&{skill_artifacts:n.skillArtifacts},...V!==void 0&&{user_instruction:V},latency_ms:Z,...T&&{tokens_input:T},...h&&{tokens_output:h},cost_usd:Q,...n.model?{model:n.model}:{},toolCount:S,errorCount:d,stopReason:r,sessionId:n.sessionId,tools:q.length?q:void 0}),P=I(k(n.prompt,w.TRACE_INPUT)),Ie=$(u(m.TRACE_NAME,n.traceName),u(m.TRACE_INPUT,P),u(m.TRACE_OUTPUT,g),u(m.OBS_INPUT,P),u(m.OBS_OUTPUT,g),u(m.TRACE_METADATA,tt),u(m.SESSION_ID,n.sessionId),u(m.USER_ID,s.user),u(m.OBS_TYPE,"GENERATION"),u(m.MODEL,n.model),T?u(m.INPUT_TOKENS,T):null,h?u(m.OUTPUT_TOKENS,h):null,u("claude.stop_reason",r),u("claude.tool_count",String(S)),u("claude.error_count",String(d)),u("claude.session_id",n.sessionId),u("flow.trace_type",X),{key:m.TRACE_TAGS,value:{arrayValue:{values:[{stringValue:X}]}}}),Pe={traceId:n.traceId,spanId:n.spanId,name:n.traceName,kind:1,startTimeUnixNano:n.startNs,endTimeUnixNano:o,attributes:Ie,status:{code:d>0?2:1}},Ne=$(u("service.name",process.env.LANGFUSE_PROJECT_NAME||"claude-code"),u("deployment.environment",process.env.LANGFUSE_ENVIRONMENT||"default")),Ct=[...l,Pe];a("Stop",`sid=${e}`,`totalTools=${S}`,`errorTools=${d}`,`spans=${Ct.length}`,`inputTokens=${T}`,`outputTokens=${h}`,`traceOutput="${ct(g,80)}"`);let be=await ye(de(Ne,Ct));a("Stop",`POST status=${be}`,`traceId=${n.traceId}`),C("TRACE_SENT",{latencyMs:Z,totalTools:S,errorTools:d,inputTokens:T,outputTokens:h,costUsd:Q}),Pt(e),O(t);}async function Jr(){let t=process.argv[2];if(t==="UserPromptSubmit"){let r=await Lt(),n;try{n=await v();}catch{process.stdout.write(JSON.stringify(r));return}n.authError?await bt(r,true):n.length>0?await bt(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 Lt();switch(t){case "PreToolUse":await pe(e);break;case "PostToolUse":await we(e);break;case "Stop":await Re(e);break;default:process.stderr.write(`[flow-obs] unknown event: ${t}
|
|
15
|
+
`),process.stdout.write(JSON.stringify(e));}}Jr().catch(t=>{process.stderr.write(`[flow-obs] fatal: ${t.message}
|
|
16
16
|
`),process.exit(0);});
|
package/dist/setup.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
'use strict';var child_process=require('child_process'),util=require('util'),i=require('fs'),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
|
-
`,{encoding:"utf8",mode:384});try{i__namespace.chmodSync(e,384);}catch{}}finally{
|
|
4
|
-
`,{encoding:"utf8",mode:384});try{i__namespace.chmodSync(t,384);}catch{}}finally{pe(r);}}var
|
|
2
|
+
'use strict';var child_process=require('child_process'),util=require('util'),i=require('fs'),u=require('path'),l=require('os'),Ke=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 Ke__default=/*#__PURE__*/_interopDefault(Ke);var _e=Object.defineProperty;var _=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,r)=>(typeof require<"u"?require:t)[r]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var A=(e,t,r)=>()=>{if(r)throw r[0];try{return e&&(t=e(e=0)),t}catch(n){throw r=[n],n}};var Te=(e,t)=>()=>{try{return t||e((t={exports:{}}).exports,t),t.exports}catch(r){throw t=0,r}},L=(e,t)=>{for(var r in t)_e(e,r,{get:t[r],enumerable:true});};var J={};L(J,{MacOsKeyVaultProvider:()=>N});var C,N,K=A(()=>{"use strict";C=util.promisify(child_process.execFile),N=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 q={};L(q,{LinuxKeyVaultProvider:()=>U});var X,U,z=A(()=>{"use strict";X=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 X("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 X("secret-tool",["clear","service",t,"account",r]),!0}catch{return !1}}getStoragePath(){return "Linux Secret Service (libsecret)"}};});var Z={};L(Z,{WindowsKeyVaultProvider:()=>b});var b,Q=A(()=>{"use strict";b=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 de=Te((ir,Je)=>{Je.exports={name:"@ciandt-flow/flow-ai-obs",version:"0.7.0-beta.582",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 Se="https://flow.ciandt.com";function R(){let e=process.env.FLOW_BASE_URL;return e&&e.trim()?e.trim():Se}function k(){let e=R();return {AUTH_ENGINE:process.env.FLOW_AUTH_ENGINE_URL||`${e}/auth-engine-api/v2/api-key/token`,GATEWAY_TRACES:process.env.FLOW_GATEWAY_TRACES_URL||`${e}/flow-langfuse-gateway/v1/traces`,GATEWAY_HEALTH:process.env.FLOW_GATEWAY_HEALTH_URL||`${e}/flow-langfuse-gateway/v1/health`,OTEL_ENDPOINT:process.env.FLOW_OTEL_ENDPOINT_URL||`${e}/otel`}}var we=k(),T={SERVICE:"flow-plugins-cli",ACCOUNT_CREDS:"credentials"},S="FLOW-nodejs",w="config.json";function V(){let e=R();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 W={CLAUDE_CODE_ENABLE_TELEMETRY:"1",OTEL_EXPORTER_OTLP_ENDPOINT:we.OTEL_ENDPOINT,OTEL_EXPORTER_OTLP_PROTOCOL:"http/json",OTEL_TRACES_EXPORTER:"otlp",OTEL_METRICS_EXPORTER:"otlp",OTEL_LOGS_EXPORTER:"otlp",OTEL_LOG_TOOL_DETAILS:"1",OTEL_LOG_USER_PROMPTS:"1"},d={FLOW_TELEMETRY:"FLOW_TELEMETRY",FLOW_TELEMETRY_GATEWAY:"FLOW_TELEMETRY_GATEWAY_URL",LANGFUSE_BASE_URL:"LANGFUSE_BASE_URL",LANGFUSE_PUBLIC_KEY:"LANGFUSE_PUBLIC_KEY",LANGFUSE_SECRET_KEY:"LANGFUSE_SECRET_KEY",ANTHROPIC_MODEL:"ANTHROPIC_MODEL",ANTHROPIC_AUTH_TOKEN:"ANTHROPIC_AUTH_TOKEN",FLOW_OBS_DEBUG:"FLOW_TELEMETRY_DEBUG",FLOW_OBS_ALLOW_HTTP:"FLOW_TELEMETRY_ALLOW_HTTP",BUFFER_TTL_DAYS:"FLOW_TELEMETRY_BUFFER_TTL_DAYS",BUFFER_MAX_FILES:"FLOW_TELEMETRY_BUFFER_MAX_FILES",FLOW_USER_EMAIL:"FLOW_USER_EMAIL"};var j={LOCK_STALE_MS:3e4},Y={UserPromptSubmit:5,PreToolUse:3,PostToolUse:10,Stop:15};var G="flow-ai-obs-debug.log";var P={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",S,w);if(process.platform==="win32"){let r=process.env.APPDATA??u__namespace.default.join(e,"AppData","Roaming");return u__namespace.default.join(r,S,w)}let t=process.env.XDG_CONFIG_HOME??u__namespace.default.join(e,".config");return u__namespace.default.join(t,S,w)}function I(){try{let e=i__namespace.default.readFileSync(m(),"utf8");return JSON.parse(e)}catch{return {}}}function B(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=I(),s=P[r]??r,o=n[s];return o?typeof o=="string"?o:JSON.stringify(o):null}async setSecret(t,r,n){let s=I(),o=P[r]??r;if(r==="token-cache")try{s[o]=JSON.parse(n);}catch{s[o]=n;}else s[o]=n;B(s);}async deleteSecret(t,r){let n=I(),s=P[r]??r;return s in n?(delete n[s],B(n),true):false}getStoragePath(){return `config.json (unencrypted) \u2014 ${m()}`}};async function ee(){return await Ue()??new v}async function Ue(){switch(process.platform){case "darwin":{let{MacOsKeyVaultProvider:e}=await Promise.resolve().then(()=>(K(),J));return await e.isAvailable()?new e:null}case "linux":{let{LinuxKeyVaultProvider:e}=await Promise.resolve().then(()=>(z(),q));return await e.isAvailable()?new e:null}case "win32":{let{WindowsKeyVaultProvider:e}=await Promise.resolve().then(()=>(Q(),Z));return await e.isAvailable()?new e:null}default:return null}}var be=T.SERVICE,Fe=T.ACCOUNT_CREDS,F=null;function $e(){return F||(F=ee()),F}async function te(){let t=await(await $e()).getSecret(be,Fe);if(!t)return null;try{return JSON.parse(t)}catch{return null}}u.join(l.tmpdir(),G);!process.env.NO_COLOR&&process.stdout.isTTY;function $(){return process.platform==="win32"?false:process.getuid?.()===0}function re(){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 ne="flow-ai-obs",se="config.json";function ie(){if(process.platform==="win32"){let r=process.env.APPDATA||u__namespace.join(l__namespace.homedir(),"AppData","Roaming");return u__namespace.join(r,ne,se)}let e=re(),t=process.env.XDG_CONFIG_HOME||u__namespace.join(e.home,".config");return u__namespace.join(t,ne,se)}var Ye=j.LOCK_STALE_MS;function ae(e){try{let t=i__namespace.statSync(e);Date.now()-t.mtimeMs>Ye&&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 ce(e){try{i__namespace.unlinkSync(e);}catch{}}function Ge(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 le(){let e=O(),t=e+".lock",r=[];i__namespace.mkdirSync(u__namespace.dirname(e),{recursive:true}),ae(t);try{if(i__namespace.existsSync(e)){i__namespace.copyFileSync(e,e+".bkp");try{i__namespace.chmodSync(e+".bkp",384);}catch{}}let n=ie();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,...W,...V()},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"],H=s.hooks;for(let c of E){let y=Ge(H[c],a(c,Y[c]));y.length>1&&r.push(c),H[c]=y;}i__namespace.writeFileSync(e,JSON.stringify(s,null,2)+`
|
|
3
|
+
`,{encoding:"utf8",mode:384});try{i__namespace.chmodSync(e,384);}catch{}}finally{ce(t);}return {settingsPath:e,preserved:r}}function ue(e){let t=O(),r=t+".lock";i__namespace.mkdirSync(u__namespace.dirname(t),{recursive:true}),ae(r);try{let n={};try{n=JSON.parse(i__namespace.readFileSync(t,"utf8"));}catch{}(!n.env||typeof n.env!="object")&&(n.env={}),Object.assign(n.env,e),i__namespace.writeFileSync(t,JSON.stringify(n,null,2)+`
|
|
4
|
+
`,{encoding:"utf8",mode:384});try{i__namespace.chmodSync(t,384);}catch{}}finally{ce(r);}}function pe(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 fe(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 M;function ge(){return M||(M=de()),M}var he=u__namespace.default.join(l__namespace.default.tmpdir(),"flow-obs-update-cache.json"),ze=1440*60*1e3,Ze=3e3;function Qe(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 et(){try{let e=JSON.parse(i__namespace.default.readFileSync(he,"utf8"));return typeof e.latestVersion!="string"||Date.now()-e.checkedAt>=ze?null:e}catch{return null}}function tt(e,t,r=Date.now()){try{i__namespace.default.writeFileSync(he,JSON.stringify({latestVersion:e,updatePriority:t??null,checkedAt:r}),{mode:384});}catch{}}function rt(e){let t=ge().name,r=Ke__default.default.get(`https://registry.npmjs.org/${encodeURIComponent(t)}/latest`,{timeout:Ze},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 Ee(){try{if(et())return;setImmediate(()=>{rt((e,t)=>{e||!t||Qe(ge().version,t.version)&&tt(t.version,t.updatePriority,0);});});}catch{}}var nt=u__namespace.default.resolve(__dirname,".."),st=process.env.INIT_CWD?u__namespace.default.resolve(process.env.INIT_CWD):null;st===nt&&process.exit(0);$()&&(process.stderr.write(`
|
|
5
5
|
[flow-ai-obs] \u2717 Do not install with sudo.
|
|
6
6
|
Run without sudo: npm install -g @ciandt-flow/flow-ai-obs
|
|
7
7
|
|
|
8
|
-
`),process.exit(1));async function
|
|
8
|
+
`),process.exit(1));async function ot(){try{le();}catch{}let e=await te();if(!e){process.stderr.write(`
|
|
9
9
|
[flow-ai-obs] No credentials found.
|
|
10
10
|
Run \`flow-ai-obs auth login\` to authenticate and enable telemetry.
|
|
11
11
|
|
|
12
|
-
`);return}let t=
|
|
12
|
+
`);return}let t=pe(process.env[d.ANTHROPIC_AUTH_TOKEN]);if(!t||t.clientId!==e.clientId||t.clientSecret!==e.clientSecret||t.tenant!==e.tenant)try{let n=fe(e);ue({[d.ANTHROPIC_AUTH_TOKEN]:n});}catch{}}ot().catch(()=>{}).finally(()=>Ee());
|