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