@ciandt-flow/flow-ai-obs 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +56 -41
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
'use strict';var c=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,n)=>(typeof require<"u"?require:t)[n]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var d=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var
|
|
2
|
+
'use strict';var c=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,n)=>(typeof require<"u"?require:t)[n]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var d=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var fe=d((sa,Qn)=>{Qn.exports={name:"@ciandt-flow/flow-ai-obs",version:"0.2.0",description:"Claude Code hooks for Langfuse OTLP tracing \u2014 cross-platform",main:"dist/index.js",bin:{"flow-ai-obs":"dist/cli.js","flow-ai-obs-setup":"dist/setup.js"},scripts:{build:"tsup",test:"node --test src/**/*.test.js",typecheck:"node --check src/**/*.js bin/cli.js",lint:"node --check src/**/*.js bin/cli.js","security-scan":"trufflehog filesystem src/ --fail --no-update --exclude-paths .trufflehogignore",postinstall:"node dist/setup.js",prepublishOnly:"npm run security-scan && npm run build","release:npm":"changeset publish",changeset:"changeset","version-packages":"changeset version","install:hooks":"node bin/cli.js install","auth:login":"node bin/cli.js auth login","auth:logout":"node bin/cli.js auth logout","auth:status":"node bin/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:false,dependencies:{keytar:"7.9.0"},devDependencies:{"@changesets/changelog-github":"^0.6.0","@changesets/cli":"^2.30.0",tsup:"^8.5.1",typescript:"^6.0.3"},engines:{node:">=18.0.0"},publishConfig:{registry:"https://registry.npmjs.org",access:"public"},repository:{type:"git",url:"git+https://github.com/CI-T-HyperX/flow-codeassistant-observability.git"}};});var W=d((ra,ot)=>{var es=!process.env.NO_COLOR&&process.stdout.isTTY;function R(e,t){return es?n=>`\x1B[${e}m${n}\x1B[${t}m`:n=>n}var ts=R("32","39"),ns=R("31","39"),ss=R("33","39"),rs=R("36","39"),os=R("1","22"),is=R("2","22");ot.exports={green:ts,red:ns,yellow:ss,cyan:rs,bold:os,dim:is};});var ke=d((oa,lt)=>{var as=c("https"),ct=c("fs"),cs=c("os"),us=c("path"),{spawn:ls}=c("child_process"),Ae;function P(){return Ae||(Ae=fe()),Ae}var ut=us.join(cs.tmpdir(),"flow-obs-update-cache.json"),ds=1440*60*1e3,ps=3e3;function Ie(e,t){let n=r=>{let i=String(r).replace(/^v/,"").match(/^(\d+)\.(\d+)\.(\d+)/);return i?[+i[1],+i[2],+i[3]]:null},s=n(e),o=n(t);return !s||!o?false:o[0]!==s[0]?o[0]>s[0]:o[1]!==s[1]?o[1]>s[1]:o[2]>s[2]}function fs(){try{let e=JSON.parse(ct.readFileSync(ut,"utf8"));return typeof e.latestVersion!="string"||Date.now()-e.checkedAt>=ds?null:e}catch{return null}}function hs(e,t){try{ct.writeFileSync(ut,JSON.stringify({latestVersion:e,updatePriority:t||null,checkedAt:Date.now()}),{mode:384});}catch{}}function Ss(e){let t=P().name,n=as.get(`https://registry.npmjs.org/${encodeURIComponent(t)}/latest`,{timeout:ps},s=>{if(s.statusCode!==200)return s.resume(),e(new Error(`HTTP ${s.statusCode}`));let o="";s.setEncoding("utf8"),s.on("data",r=>{o+=r;}),s.on("end",()=>{try{let r=JSON.parse(o);if(typeof r.version!="string")throw new Error("no version field");e(null,{version:r.version,updatePriority:typeof r.updatePriority=="string"?r.updatePriority:null});}catch(r){e(r);}});});n.on("error",e),n.on("timeout",()=>{n.destroy(new Error("timeout"));});}function it(e){let t=P().name,s=` Update available: ${P().version} \u2192 ${e}`,o=` Run: npm install -g ${t}`,r=Math.max(s.length,o.length)+2,i="\u2500".repeat(r);process.stderr.write(`
|
|
3
3
|
\u256D${i}\u256E
|
|
4
4
|
\u2502${s.padEnd(r)}\u2502
|
|
5
5
|
\u2502${o.padEnd(r)}\u2502
|
|
6
6
|
\u2570${i}\u256F
|
|
7
7
|
|
|
8
|
-
`);}function
|
|
8
|
+
`);}function at(e){let t=P().name;process.stderr.write(`
|
|
9
9
|
[${t}] Critical update detected \u2014 auto-updating to ${e}...
|
|
10
10
|
|
|
11
|
-
`),
|
|
12
|
-
`,"utf8");}finally{
|
|
11
|
+
`),ls("npm",["install","-g",`${t}@${e}`],{detached:true,stdio:"ignore",windowsHide:true}).unref();}function Es(){try{let e=fs();if(e){Ie(P().version,e.latestVersion)&&(e.updatePriority==="auto"?at(e.latestVersion):it(e.latestVersion));return}setImmediate(()=>{Ss((t,n)=>{t||!n||(hs(n.version,n.updatePriority),Ie(P().version,n.version)&&(n.updatePriority==="auto"?at(n.version):it(n.version)));});});}catch{}}lt.exports={checkForUpdate:Es,isNewer:Ie};});var w=d((ia,pt)=>{var H=process.env.FLOW_BASE_URL||"https://flow.ciandt.com",dt={AUTH_ENGINE:process.env.FLOW_AUTH_ENGINE_URL||`${H}/auth-engine-api/v2/api-key/token`,GATEWAY_TRACES:process.env.FLOW_GATEWAY_TRACES_URL||`${H}/flow-langfuse-gateway/v1/traces`,GATEWAY_HEALTH:process.env.FLOW_GATEWAY_HEALTH_URL||`${H}/flow-langfuse-gateway/v1/health`,OTEL_ENDPOINT:process.env.FLOW_OTEL_ENDPOINT_URL||`${H}/otel`},Ts={SERVICE:"flow-plugins-cli",ACCOUNT_CREDS:"credentials",ACCOUNT_TOKEN:"token-cache"},ws="FLOW-nodejs",gs="config.json",_s={SCOPE_NAME:"flow-ai-obs",SCOPE_VERSION:"0.1.0"},ms={CLAUDE_CODE_ENABLE_TELEMETRY:"1",OTEL_EXPORTER_OTLP_ENDPOINT:dt.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"},ys={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",FLOW_OBS_DEBUG:"FLOW_TELEMETRY_DEBUG",FLOW_OBS_ALLOW_HTTP:"FLOW_TELEMETRY_ALLOW_HTTP"},Os={LOCK_STALE_MS:3e4,CONNECTIVITY_MAX_RETRY:3,CONNECTIVITY_RETRY_MS:2e3},Ls={UserPromptSubmit:5,PreToolUse:3,PostToolUse:10,Stop:15},As={FILE_PREFIX:"flow-obs-buffer-",MAX_AGE_MS:5760*60*1e3,MAX_FILES:50},Is="flow-ai-obs-debug.log",ks={TOOL_INPUT:2e4,TOOL_OUTPUT:2e4,TRACE_OUTPUT:2e4,USER_INSTRUCTION:1e4,TRACE_INPUT:5e4,TOOL_BRIEF:60},Ns="flow-obs-";pt.exports={FLOW_BASE_URL:H,FLOW_URLS:dt,VAULT:Ts,CONFIG_DIR_NAME:ws,CONFIG_FILE_NAME:gs,OTLP:_s,NATIVE_OTEL:ms,ENV:ys,INSTALLER:Os,HOOK_TIMEOUTS:Ls,BUFFER:As,DEBUG_LOG_FILENAME:Is,STATE_FILE_PREFIX:Ns,TRACE_LIMITS:ks};});var K=d((aa,ht)=>{var Cs=c("https"),bs=c("http"),{FLOW_URLS:Us}=w(),vs=/^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$|^[a-z0-9]$/;function Rs(e){if(!vs.test(e))throw new Error(`Invalid tenant value: "${e}". Tenant must be lowercase alphanumeric and hyphens (1-64 chars).`)}var ft={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 Ps(e,t){try{let n=JSON.parse(t);if(typeof n.error=="string"&&ft[n.error])return new Error(ft[n.error])}catch{}return e===401||e===403||e===500?new Error("Invalid credentials"):e>=400&&e<500?new Error("Authentication request was rejected"):new Error("Authentication service unavailable, please try again later")}function $s(e){return new Promise((t,n)=>{try{Rs(e.tenant);}catch(l){return n(l)}let s=JSON.stringify({clientSecret:e.clientSecret}),o=new URL(Us.AUTH_ENGINE),r=o.protocol==="https:",i={hostname:o.hostname,port:o.port||(r?443:80),path:o.pathname+o.search,method:"POST",headers:{"Content-Type":"application/json","Content-Length":Buffer.byteLength(s),FlowTenant:e.tenant}},p=(r?Cs:bs).request(i,l=>{let u=[];l.on("data",h=>u.push(h)),l.on("end",()=>{let h=u.join("");if(l.statusCode>=400)return n(Ps(l.statusCode,h));let E;try{E=JSON.parse(h);}catch{return n(new Error("Invalid response from auth engine"))}let m=E.expires_at??new Date(Date.now()+(E.expires_in??3600)*1e3).toISOString();t({accessToken:E.access_token,expiresAt:m});});});p.on("error",l=>n(new Error(`Network error: ${l.message}`))),p.write(s),p.end();})}ht.exports={getToken:$s};});var Ce=d((ca,Tt)=>{var y=c("fs"),Se=c("path"),St=c("os"),{FLOW_URLS:qs,INSTALLER:J,HOOK_TIMEOUTS:he,NATIVE_OTEL:Fs}=w(),{getToken:xs}=K();function Et(){return process.platform==="win32"?Se.join(process.env.APPDATA||Se.join(St.homedir(),"AppData","Roaming"),"Claude","settings.json"):Se.join(St.homedir(),".claude","settings.json")}var Ms=J.LOCK_STALE_MS;function Bs(e){try{let t=y.statSync(e);Date.now()-t.mtimeMs>Ms&&y.unlinkSync(e);}catch{}try{y.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 Ds(e){try{y.unlinkSync(e);}catch{}}function Gs(){let e=Et(),t=e+".lock";y.mkdirSync(Se.dirname(e),{recursive:true}),Bs(t);try{y.existsSync(e)&&y.copyFileSync(e,e+".bkp");let n={};try{n=JSON.parse(y.readFileSync(e,"utf8"));}catch{}(!n.env||typeof n.env!="object")&&(n.env={}),Object.assign(n.env,Fs),n.otelHeadersHelper="flow-ai-obs otel-headers",(!n.hooks||typeof n.hooks!="object")&&(n.hooks={});let s=(o,r)=>({matcher:"",hooks:[{type:"command",command:`flow-ai-obs ${o}`,timeout:r}]});n.hooks.UserPromptSubmit=[s("UserPromptSubmit",he.UserPromptSubmit)],n.hooks.PreToolUse=[s("PreToolUse",he.PreToolUse)],n.hooks.PostToolUse=[s("PostToolUse",he.PostToolUse)],n.hooks.Stop=[s("Stop",he.Stop)],y.writeFileSync(e,JSON.stringify(n,null,2)+`
|
|
12
|
+
`,"utf8");}finally{Ds(t);}return e}async function js(e){let t;try{t=(await xs(e)).accessToken;}catch{return false}return t?new Promise(n=>{Ne(`Bearer ${t}`,n,1);}):false}function Ne(e,t,n){let s=new URL(qs.GATEWAY_TRACES),o=JSON.stringify({resourceSpans:[],validation_run:true}),r=s.protocol==="https:",i={hostname:s.hostname,port:s.port||(r?443:80),path:s.pathname,method:"POST",headers:{"Content-Type":"application/json",Authorization:e,"Content-Length":Buffer.byteLength(o)}},p=(r?c("https"):c("http")).request(i,l=>{l.resume(),l.statusCode===200||l.statusCode===204?t(true):n<J.CONNECTIVITY_MAX_RETRY?setTimeout(()=>Ne(e,t,n+1),J.CONNECTIVITY_RETRY_MS):t(false);});p.on("error",()=>{n<J.CONNECTIVITY_MAX_RETRY?setTimeout(()=>Ne(e,t,n+1),J.CONNECTIVITY_RETRY_MS):t(false);}),p.write(o),p.end();}Tt.exports={getClaudeSettingsPath:Et,writeClaudeSettings:Gs,validateConnectivity:js};});var _t=d((ua,gt)=>{var X=c("fs"),$=c("path"),Vs=c("os"),{CONFIG_DIR_NAME:be,CONFIG_FILE_NAME:Ue}=w(),ve={credentials:"credentials","token-cache":"tokenCache"};function z(){let e=Vs.homedir();if(process.platform==="darwin")return $.join(e,"Library","Preferences",be,Ue);if(process.platform==="win32"){let n=process.env.APPDATA||$.join(e,"AppData","Roaming");return $.join(n,be,Ue)}let t=process.env.XDG_CONFIG_HOME||$.join(e,".config");return $.join(t,be,Ue)}function Re(){try{let e=X.readFileSync(z(),"utf8");return JSON.parse(e)}catch{return {}}}function wt(e){let t=z();X.mkdirSync($.dirname(t),{recursive:true}),X.writeFileSync(t,JSON.stringify(e,null,2),{encoding:"utf8",mode:384});}var Pe=class{static isAvailable(){return true}static hasExistingData(){try{if(!X.existsSync(z()))return !1;let t=JSON.parse(X.readFileSync(z(),"utf8"));return !!(t&&t.credentials)}catch{return false}}async getSecret(t,n){let s=Re(),o=ve[n]||n,r=s[o];return r?typeof r=="string"?r:JSON.stringify(r):null}async setSecret(t,n,s){let o=Re(),r=ve[n]||n;if(n==="token-cache")try{o[r]=JSON.parse(s);}catch{o[r]=s;}else o[r]=s;wt(o);}async deleteSecret(t,n){let s=Re(),o=ve[n]||n;return o in s?(delete s[o],wt(s),true):false}getStoragePath(){return `config.json (unencrypted) \u2014 ${z()}`}};function Ys(){}gt.exports={ScryptFallbackProvider:Pe,_resetWarningState:Ys};});var yt=d((la,mt)=>{var{VAULT:Z}=w();async function Ws(e,t){let n=[Z.ACCOUNT_CREDS,Z.ACCOUNT_TOKEN];for(let s of n)try{if(await t.getSecret(Z.SERVICE,s)!==null)continue;let r=await e.getSecret(Z.SERVICE,s);r!==null&&await t.setSecret(Z.SERVICE,s,r);}catch{}}mt.exports={migrateFromJsonFallback:Ws};});var At=d((da,Lt)=>{var{execFile:Hs,exec:Ks}=c("child_process"),{promisify:Ot}=c("util"),$e=Ot(Hs),Js=Ot(Ks),qe=class{static async isAvailable(){try{return await Js("command -v security"),!0}catch{return false}}async getSecret(t,n){try{let{stdout:s}=await $e("security",["find-generic-password","-w","-a",n,"-s",t]);return s.trim()||null}catch{return null}}async setSecret(t,n,s){await $e("security",["add-generic-password","-U","-a",n,"-s",t,"-w",s]);}async deleteSecret(t,n){try{return await $e("security",["delete-generic-password","-a",n,"-s",t]),!0}catch{return false}}getStoragePath(){return "macOS Keychain"}};Lt.exports={MacOsKeyVaultProvider:qe};});var Ct=d((pa,Nt)=>{var{execFile:zs,exec:Xs,spawn:Zs}=c("child_process"),{promisify:kt}=c("util"),It=kt(zs),Qs=kt(Xs),Fe=class{static async isAvailable(){try{return await Qs("command -v secret-tool"),!0}catch{return false}}async getSecret(t,n){try{let{stdout:s}=await It("secret-tool",["lookup","service",t,"account",n]);return s.trim()||null}catch{return null}}async setSecret(t,n,s){await new Promise((o,r)=>{let i=Zs("secret-tool",["store","--label",t,"service",t,"account",n]);i.on("error",r),i.on("close",a=>{a===0?o():r(new Error(`secret-tool exited with code ${a}`));}),i.stdin.write(s),i.stdin.end();});}async deleteSecret(t,n){try{return await It("secret-tool",["clear","service",t,"account",n]),!0}catch{return false}}getStoragePath(){return "Linux Secret Service (libsecret)"}};Nt.exports={LinuxKeyVaultProvider:Fe};});var Ut=d((fa,bt)=>{var xe=class{static async isAvailable(){try{return await c("keytar").getPassword("__flow_probe__","__flow_probe__"),!0}catch{return false}}async getSecret(t,n){return c("keytar").getPassword(t,n)}async setSecret(t,n,s){await c("keytar").setPassword(t,n,s);}async deleteSecret(t,n){return c("keytar").deletePassword(t,n)}getStoragePath(){return "Windows Credential Manager"}};bt.exports={WindowsKeyVaultProvider:xe};});var $t=d((ha,Pt)=>{async function Rt(){let{ScryptFallbackProvider:e}=_t();if(e.hasExistingData()){let t=await vt();if(t){let{migrateFromJsonFallback:n}=yt(),{VAULT:s}=w();if(await n(new e,t),await t.getSecret(s.SERVICE,s.ACCOUNT_CREDS)!==null)return t}return new e}return await vt()??new e}async function vt(){switch(process.platform){case "darwin":{let{MacOsKeyVaultProvider:e}=At();return await e.isAvailable()?new e:null}case "linux":{let{LinuxKeyVaultProvider:e}=Ct();return await e.isAvailable()?new e:null}case "win32":{let{WindowsKeyVaultProvider:e}=Ut();return await e.isAvailable()?new e:null}default:return null}}var er=Rt;Pt.exports={createSecretVaultProvider:Rt,createKeyVaultProvider:er};});var x=d((Sa,Ft)=>{var{createSecretVaultProvider:tr}=$t(),{VAULT:Be}=w(),q=Be.SERVICE,De=Be.ACCOUNT_CREDS,Ge=Be.ACCOUNT_TOKEN,Me=null;function F(){return Me||(Me=tr()),Me}async function qt(){let t=await(await F()).getSecret(q,De);if(!t)return null;try{return JSON.parse(t)}catch{return null}}async function nr(e){if(!e.clientId||!e.clientSecret||!e.tenant)throw new Error("clientId, clientSecret and tenant are required");await(await F()).setSecret(q,De,JSON.stringify(e));}async function sr(){let e=await F();await e.deleteSecret(q,De),await e.deleteSecret(q,Ge);}async function rr(e){await(await F()).setSecret(q,Ge,JSON.stringify({accessToken:e.accessToken,expiresAt:e.expiresAt}));}async function je(){let t=await(await F()).getSecret(q,Ge);if(!t)return null;try{let n=JSON.parse(t);return {accessToken:n.accessToken,expiresAt:n.expiresAt}}catch{return null}}async function or(){let e=await je();return e?new Date(e.expiresAt)>new Date:false}async function ir(){let e=await je();if(!e||!e.accessToken)return null;try{let t=e.accessToken.split(".");if(t.length<2)return null;let n=JSON.parse(Buffer.from(t[1].replace(/-/g,"+").replace(/_/g,"/"),"base64").toString("utf8"));return n.email||n.preferred_username||n.upn||n.sub||null}catch{return null}}async function ar(){let e=await F();if(typeof e.getStoragePath=="function")return e.getStoragePath();let t=process.platform;return t==="darwin"?"macOS Keychain":t==="win32"?"Windows Credential Manager":"Linux Secret Service (libsecret)"}async function cr(){let e=await qt();return !!(e&&e.clientId&&e.clientSecret&&e.tenant)}Ft.exports={getFlowCredentials:qt,saveFlowCredentials:nr,clearFlowCredentials:sr,saveTokenCache:rr,getTokenCache:je,isTokenValid:or,getEmailFromToken:ir,getConfigPath:ar,hasCredentials:cr};});var Bt=d((Ea,Mt)=>{var{writeClaudeSettings:ur}=Ce(),{hasCredentials:lr}=x(),{NATIVE_OTEL:dr}=w(),{green:pr,yellow:fr,bold:xt,dim:O,cyan:hr}=W();async function Sr(){let e=await lr(),t;try{t=ur();}catch(n){return process.stderr.write(` \u2717 Failed to write settings: ${n.message}
|
|
13
13
|
`),1}process.stdout.write(`
|
|
14
14
|
`+xt(" Native OTEL configured")+` (metrics & logs)
|
|
15
15
|
`);for(let[n,s]of Object.entries(dr))process.stdout.write(O(` ${n.padEnd(36)}`)+s+`
|
|
@@ -29,72 +29,87 @@
|
|
|
29
29
|
`)):process.stdout.write(fr(` \u26A0 Not authenticated \u2014 hooks registered, but trace forwarding is inactive.
|
|
30
30
|
`)+" Run "+hr("flow-ai-obs auth login")+` to activate Langfuse tracing.
|
|
31
31
|
|
|
32
|
-
`),0}Mt.exports={runInstall:Sr};});var Ht=d((Ta,Wt)=>{var{getFlowCredentials:Dt,saveFlowCredentials:Er,clearFlowCredentials:Tr,saveTokenCache:wr,isTokenValid:gr,getConfigPath:Gt,hasCredentials:jt}=
|
|
32
|
+
`),0}Mt.exports={runInstall:Sr};});var Ht=d((Ta,Wt)=>{var{getFlowCredentials:Dt,saveFlowCredentials:Er,clearFlowCredentials:Tr,saveTokenCache:wr,isTokenValid:gr,getConfigPath:Gt,hasCredentials:jt}=x(),{getToken:_r}=K(),{green:Te,red:Q,yellow:Ee,cyan:ee,bold:Vt,dim:M}=W(),mr=/[\x00-\x08\x0B-\x1F\x7F]|\x1b\[[0-9;]*[a-zA-Z]/g;function k(e){return typeof e=="string"?e.replace(mr,""):e}function te(e,t={}){return new Promise((n,s)=>{let{masked:o=false,defaultValue:r=""}=t;process.stdout.write(e+r);let i=r;function a(){try{process.stdin.setRawMode(!1);}catch{}}process.once("uncaughtException",a),process.once("unhandledRejection",a);let p=u=>{if(u===""){l(),s(new Error("SIGINT"));return}if(u==="\r"||u===`
|
|
33
33
|
`){l(),process.stdout.write(`
|
|
34
|
-
`),n(i);return}if(u==="\x7F"){i.length>0&&(i=i.slice(0,-1),process.stdout.write("\b \b"));return}u.startsWith("\x1B")||(i+=u,process.stdout.write(o?"*".repeat(u.length):u));};function l(){process.stdin.setRawMode(false),process.stdin.removeListener("data",p),process.removeListener("uncaughtException",a),process.removeListener("unhandledRejection",a);}process.stdin.setRawMode(true),process.stdin.resume(),process.stdin.setEncoding("utf8"),process.stdin.on("data",p);})}async function Yt(e){let{accessToken:t,expiresAt:n}=await _r(e);await Er(e),await wr({accessToken:t,expiresAt:n});}async function yr(e){try{return await Yt(e),process.stdout.write(
|
|
34
|
+
`),n(i);return}if(u==="\x7F"){i.length>0&&(i=i.slice(0,-1),process.stdout.write("\b \b"));return}u.startsWith("\x1B")||(i+=u,process.stdout.write(o?"*".repeat(u.length):u));};function l(){process.stdin.setRawMode(false),process.stdin.removeListener("data",p),process.removeListener("uncaughtException",a),process.removeListener("unhandledRejection",a);}process.stdin.setRawMode(true),process.stdin.resume(),process.stdin.setEncoding("utf8"),process.stdin.on("data",p);})}async function Yt(e){let{accessToken:t,expiresAt:n}=await _r(e);await Er(e),await wr({accessToken:t,expiresAt:n});}async function yr(e){try{return await Yt(e),process.stdout.write(Te(` \u2713 Setup complete. Tenant: ${k(e.tenant)}
|
|
35
35
|
|
|
36
|
-
`)),0}catch(t){return process.stderr.write(
|
|
36
|
+
`)),0}catch(t){return process.stderr.write(Q(` \u2717 Authentication failed: ${k(t.message)}
|
|
37
37
|
`)),1}}async function Or(){try{process.stdout.write(`
|
|
38
|
-
`);let e=(await
|
|
39
|
-
`)),1;try{await Yt({clientId:e,clientSecret:t,tenant:n});}catch(s){return process.stderr.write(
|
|
40
|
-
`)),1}return process.stdout.write(
|
|
38
|
+
`);let e=(await te(ee(" ? ")+"Client ID: ")).trim(),t=(await te(ee(" ? ")+"Client Secret: ",{masked:!0})).trim(),n=(await te(ee(" ? ")+"Tenant: ")).trim();if(!e||!t||!n)return process.stderr.write(Q(` \u2717 All fields are required
|
|
39
|
+
`)),1;try{await Yt({clientId:e,clientSecret:t,tenant:n});}catch(s){return process.stderr.write(Q(` \u2717 Authentication failed: ${k(s.message)}
|
|
40
|
+
`)),1}return process.stdout.write(Te(` \u2713 Setup complete. Tenant: ${k(n)}
|
|
41
41
|
`)),process.stdout.write(` Storage: ${await Gt()}
|
|
42
42
|
|
|
43
|
-
`),0}catch(e){if(e.message==="SIGINT")throw e;return process.stderr.write(
|
|
43
|
+
`),0}catch(e){if(e.message==="SIGINT")throw e;return process.stderr.write(Q(` \u2717 Unexpected error: ${e.message}
|
|
44
44
|
`)),1}}async function Lr(e={}){if(e.clientId&&e.clientSecret&&e.tenant)return yr({clientId:e.clientId,clientSecret:e.clientSecret,tenant:e.tenant});if(await jt()){let t=await Dt();process.stdout.write(`
|
|
45
45
|
`),process.stdout.write(Vt(` Already authenticated
|
|
46
|
-
`)),process.stdout.write(
|
|
47
|
-
`),process.stdout.write(
|
|
46
|
+
`)),process.stdout.write(M(" Tenant: ")+k(t.tenant)+`
|
|
47
|
+
`),process.stdout.write(M(" Client ID: ")+k(t.clientId)+`
|
|
48
48
|
`),process.stdout.write(`
|
|
49
|
-
`);let n;try{n=await
|
|
50
|
-
`),130;throw s}if(n.trim().toLowerCase()!=="y")return process.stdout.write(
|
|
49
|
+
`);let n;try{n=await te(ee(" ? ")+"Re-authenticate? (y/N): ");}catch(s){if(s.message==="SIGINT")return process.stdout.write(`
|
|
50
|
+
`),130;throw s}if(n.trim().toLowerCase()!=="y")return process.stdout.write(Te(` \u2713 Using existing credentials.
|
|
51
51
|
|
|
52
52
|
`)),0}try{return await Or()}catch(t){if(t.message==="SIGINT")return process.stdout.write(`
|
|
53
53
|
`),130;throw t}}async function Ar(){try{return process.stdout.write(`
|
|
54
|
-
`),(await
|
|
54
|
+
`),(await te(ee(" ? ")+"Are you sure? This will remove your local credentials. (y/N): ")).toLowerCase()!=="y"?(process.stdout.write(Ee(` \u26A0 Logout cancelled
|
|
55
55
|
`)),0):null}catch(e){if(e.message==="SIGINT")return process.stdout.write(`
|
|
56
|
-
`),130;throw e}}async function Ir(e=false){if(!await jt())return process.stdout.write(
|
|
57
|
-
`)),0;if(!e){let t=await Ar();if(t!==null)return t}try{return await Tr(),process.stdout.write(
|
|
58
|
-
`)),0}catch{return process.stderr.write(
|
|
59
|
-
`)),1}}async function kr(){let e=await Dt();if(!e)return process.stdout.write(
|
|
56
|
+
`),130;throw e}}async function Ir(e=false){if(!await jt())return process.stdout.write(Ee(` \u26A0 You are not authenticated
|
|
57
|
+
`)),0;if(!e){let t=await Ar();if(t!==null)return t}try{return await Tr(),process.stdout.write(Te(` \u2713 Credentials removed successfully
|
|
58
|
+
`)),0}catch{return process.stderr.write(Q(` \u2717 Error removing credentials
|
|
59
|
+
`)),1}}async function kr(){let e=await Dt();if(!e)return process.stdout.write(Ee(" \u26A0 Not authenticated. Run `flow-ai-obs auth login` to set up.\n")),0;if(!await gr())return process.stdout.write(Ee(" \u26A0 Session expired. Run `flow-ai-obs auth login` to re-authenticate.\n")),0;let t=e.clientSecret.length>4?"****...****"+e.clientSecret.slice(-4):"****";return process.stdout.write(`
|
|
60
60
|
`+Vt(` Authenticated
|
|
61
|
-
`)),process.stdout.write(
|
|
62
|
-
`),process.stdout.write(
|
|
63
|
-
`),process.stdout.write(
|
|
64
|
-
`),process.stdout.write(
|
|
61
|
+
`)),process.stdout.write(M(" Tenant: ")+k(e.tenant)+`
|
|
62
|
+
`),process.stdout.write(M(" Client ID: ")+k(e.clientId)+`
|
|
63
|
+
`),process.stdout.write(M(" Client Secret: ")+t+`
|
|
64
|
+
`),process.stdout.write(M(" Storage: ")+await Gt()+`
|
|
65
65
|
|
|
66
|
-
`),0}Wt.exports={runLogin:Lr,runLogout:Ir,runStatus:kr};});var Jt=d((wa,Kt)=>{var{getFlowCredentials:Nr}=
|
|
66
|
+
`),0}Wt.exports={runLogin:Lr,runLogout:Ir,runStatus:kr};});var Jt=d((wa,Kt)=>{var{getFlowCredentials:Nr}=x(),{getToken:Cr}=K();async function br(){let e;try{e=await Nr();}catch{return process.stderr.write(`[flow-ai-obs otel-headers] Failed to read credentials
|
|
67
67
|
`),1}if(!e)return process.stderr.write(`[flow-ai-obs otel-headers] Not authenticated \u2014 run: flow-ai-obs auth login
|
|
68
68
|
`),1;let t;try{t=(await Cr(e)).accessToken;}catch(n){return process.stderr.write(`[flow-ai-obs otel-headers] Token fetch failed: ${n.message}
|
|
69
69
|
`),1}return t?(process.stdout.write(`{"Authorization": "Bearer ${t}"}
|
|
70
70
|
`),0):(process.stderr.write(`[flow-ai-obs otel-headers] Empty token received
|
|
71
|
-
`),1)}Kt.exports={runOtelHeaders:br};});var
|
|
71
|
+
`),1)}Kt.exports={runOtelHeaders:br};});var N=d((ga,Xt)=>{var{writeFileSync:Ur}=c("fs"),{tmpdir:vr}=c("os"),{join:Rr}=c("path"),{DEBUG_LOG_FILENAME:Pr,ENV:$r}=w(),zt=Rr(vr(),Pr);function qr(...e){if(process.env[$r.FLOW_OBS_DEBUG]!=="1")return;let t=`[${new Date().toISOString()}] ${e.join(" ")}
|
|
72
72
|
`;try{Ur(zt,t,{flag:"a"});}catch(n){process.stderr.write(`[flow-obs debug ERROR] ${n.message}
|
|
73
|
-
`);}}Xt.exports={dbg:qr,DEBUG_LOG:zt};});var
|
|
74
|
-
`);}function
|
|
75
|
-
`);}function
|
|
73
|
+
`);}}Xt.exports={dbg:qr,DEBUG_LOG:zt};});var ne=d((_a,Qt)=>{var{getFlowCredentials:Ve,isTokenValid:Fr,getEmailFromToken:Ye,getTokenCache:xr,saveTokenCache:Mr}=x(),{getToken:Br}=K(),{FLOW_BASE_URL:Dr,ENV:U}=w(),{dbg:we}=N(),Gr=[/^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 jr(e){return Gr.some(t=>t.test(e))}function We(e){let t;try{t=new URL(e);}catch{throw new Error(`Invalid URL: ${e}`)}if(!(process.env[U.FLOW_OBS_ALLOW_HTTP]==="true")&&t.protocol!=="https:")throw new Error(`URL must use HTTPS: ${e}`);if(t.username||t.password)throw new Error(`URL must not contain embedded credentials: ${e}`);if(jr(t.hostname))throw new Error(`SSRF: private/loopback host not allowed: ${t.hostname}`);return e}async function Vr(){try{let e=await Ve();if(!e)return {user:"",tenant:""};let t=await Ye()||e.clientId||"",n=e.tenant||"";return {user:t,tenant:n}}catch{return {user:"",tenant:""}}}async function Yr(e){if(await Fr())return (await xr()).accessToken;we("getOrRefreshToken","token expired \u2014 refreshing via auth-engine");let t=await Br(e);return await Mr(t),we("getOrRefreshToken",`token refreshed, expires=${t.expiresAt}`),t.accessToken}function Wr(e,t){let n=t&&t.accessToken?t.accessToken:"";return {endpoint:e.replace(/\/$/,"")+"/langfuse/traces",authHeader:`Bearer ${n}`}}function Hr(e,t,n){let s=Buffer.from(`${t}:${n}`).toString("base64");return {endpoint:e.replace(/\/$/,"")+"/api/public/otel/v1/traces",authHeader:`Basic ${s}`}}async function Zt(){let e=[],t=process.env[U.ANTHROPIC_MODEL]||"",n=process.env[U.FLOW_TELEMETRY]==="true",s=process.env[U.LANGFUSE_BASE_URL],o=process.env[U.LANGFUSE_PUBLIC_KEY],r=process.env[U.LANGFUSE_SECRET_KEY];if(n&&s&&o&&r){let u="",h="";try{let m=await Ve();m&&(u=await Ye()||m.clientId,h=m.tenant);}catch{}let E={user:u||"",tenant:h||"",team:"",project:"",model:t};e.push({mode:"direct",...Hr(We(s),o,r),...E}),we("resolveCredentials","direct mode active",`user=${E.user}`,`tenant=${E.tenant}`);}let i=await Ve();if(!i){if(e.length===0){let u=[];return u.authError=false,u}return e}let a;try{a=await Yr(i);}catch(u){if(we("resolveCredentials",`token refresh failed: ${u.message}`),e.length>0)return e;let h=[];return h.authError=true,h}let p={user:await Ye()||i.clientId,tenant:i.tenant,team:"",project:"",model:t},l=process.env[U.FLOW_TELEMETRY_GATEWAY]||Dr;return e.push({mode:"gateway",...Wr(We(l),{accessToken:a}),...p}),e}async function Kr(){return (await Zt()).length>0}Qt.exports={credentialsAvailable:Kr,getIdentityFromToken:Vr,resolveCredentials:Zt,validateUrl:We};});var tn=d((ma,en)=>{var{getFlowCredentials:Jr,isTokenValid:zr,getEmailFromToken:Xr,getTokenCache:Zr}=x(),{resolveCredentials:Qr}=ne(),{getClaudeSettingsPath:eo}=Ce(),{ENV:B,NATIVE_OTEL:to}=w(),no=c("fs");function He(e){return !e||e.length<=8?"****":e.slice(0,4)+"****...****"+e.slice(-4)}function se(e){process.stdout.write(` \u2713 ${e}
|
|
74
|
+
`);}function Ke(e){process.stdout.write(` \u26A0 ${e}
|
|
75
|
+
`);}function ge(e){process.stdout.write(` \u2717 ${e}
|
|
76
76
|
`);}function g(e){process.stdout.write(` ${e}
|
|
77
77
|
`);}function L(){process.stdout.write(`
|
|
78
78
|
`);}async function so(){L(),process.stdout.write(` flow-claude-observability \u2014 configuration check
|
|
79
79
|
`),L(),process.stdout.write(` Auth
|
|
80
|
-
`);let e=await Jr();if(!e)return
|
|
81
|
-
`);let n={};try{let i=no.readFileSync(eo(),"utf8");n=JSON.parse(i).env||{};}catch{}let s=Object.keys(to).filter(i=>!n[i]);if(s.length===0?(
|
|
82
|
-
`),process.env[
|
|
83
|
-
`),L(),0}en.exports={runCheck:so};});var
|
|
84
|
-
`)[0].slice(0,t).trim()}function io(){return new Promise(e=>{let t="";process.stdin.setEncoding("utf8"),process.stdin.on("data",n=>t+=n),process.stdin.on("end",()=>{try{e(JSON.parse(t));}catch{e({});}});})}function ao(e){process.stdout.write(JSON.stringify(e));}nn.exports={truncate:ro,firstLine:oo,readInput:io,passthrough:ao};});var
|
|
80
|
+
`);let e=await Jr();if(!e)return ge("Not authenticated. Run: flow-claude-observability auth login"),L(),1;if(!await zr())return Ke("Session expired. Run: flow-claude-observability auth login"),g(`Tenant: ${e.tenant}`),g(`Client ID: ${e.clientId}`),L(),1;let t=await Xr()||e.clientId;se("Authenticated"),g(`Tenant: ${e.tenant}`),g(`User: ${t}`),L(),process.stdout.write(` Native OTEL
|
|
81
|
+
`);let n={};try{let i=no.readFileSync(eo(),"utf8");n=JSON.parse(i).env||{};}catch{}let s=Object.keys(to).filter(i=>!n[i]);if(s.length===0?(se("All OTEL env vars present in settings.json"),g(`Endpoint: ${n.OTEL_EXPORTER_OTLP_ENDPOINT}`)):(Ke(`${s.length} OTEL var(s) missing from settings.json \u2014 native metrics/logs disabled`),s.forEach(i=>ge(`Missing: ${i}`)),g("Run: flow-ai-obs install (restores missing vars automatically)")),L(),process.stdout.write(` Tracing
|
|
82
|
+
`),process.env[B.FLOW_TELEMETRY]==="true"){se("FLOW_TELEMETRY=true (direct mode enabled)");let i=[B.LANGFUSE_BASE_URL,B.LANGFUSE_PUBLIC_KEY,B.LANGFUSE_SECRET_KEY].filter(a=>!process.env[a]);i.length>0&&i.forEach(a=>Ke(`Missing: ${a}`));}else g("FLOW_TELEMETRY not set \u2014 direct mode inactive (gateway mode may still be active)");let r=await Qr();if(!r||r.length===0)return r&&r.authError?ge("Token refresh failed \u2014 gateway mode could not activate"):(ge("No active destinations \u2014 no traces will be sent"),g("For direct mode: set FLOW_TELEMETRY=true + LANGFUSE_BASE_URL + LANGFUSE_PUBLIC_KEY + LANGFUSE_SECRET_KEY"),g("For gateway mode: run flow-claude-observability auth login")),L(),1;for(let i of r)if(i.mode==="gateway"){let a=await Zr();se("Mode: gateway"),g(`Endpoint: ${i.endpoint}`),g(`Token: ${He(a&&a.accessToken)}`);}else i.mode==="direct"&&(se("Mode: direct"),g(`Endpoint: ${i.endpoint}`),g(`PK: ${He(process.env[B.LANGFUSE_PUBLIC_KEY])}`),g(`SK: ${He(process.env[B.LANGFUSE_SECRET_KEY])}`));return L(),process.stdout.write(` All checks passed \u2014 observability is active.
|
|
83
|
+
`),L(),0}en.exports={runCheck:so};});var D=d((ya,nn)=>{function ro(e,t){let n=typeof e=="object"?JSON.stringify(e):String(e??"");return n.length>t?n.slice(0,t)+" \u2026[truncated]":n}function oo(e,t=100){return String(e??"").split(`
|
|
84
|
+
`)[0].slice(0,t).trim()}function io(){return new Promise(e=>{let t="";process.stdin.setEncoding("utf8"),process.stdin.on("data",n=>t+=n),process.stdin.on("end",()=>{try{e(JSON.parse(t));}catch{e({});}});})}function ao(e){process.stdout.write(JSON.stringify(e));}nn.exports={truncate:ro,firstLine:oo,readInput:io,passthrough:ao};});var re=d((Oa,rn)=>{var{randomBytes:sn}=c("crypto"),co=()=>sn(16).toString("hex"),uo=()=>sn(8).toString("hex");function lo(){return String(BigInt(Date.now())*1000000n)}rn.exports={generateTraceId:co,generateSpanId:uo,nowNs:lo};});var oe=d((Aa,an)=>{var{readFileSync:po,writeFileSync:fo,unlinkSync:ho,existsSync:So,realpathSync:La}=c("fs"),{tmpdir:on}=c("os"),{join:Eo,resolve:To,normalize:wo,sep:go}=c("path"),_o=/^[0-9a-f-]{1,64}$/i,mo=wo(on())+go;function yo(e,t){let n=To(e);if(!n.startsWith(t))throw new Error(`Path traversal detected: ${e}`);return n}function Je(e){if(!_o.test(e))throw new Error(`Invalid session ID: ${e}`);return yo(Eo(on(),`flow-obs-${e}.json`),mo)}function Oo(e){let t=Je(e);if(!So(t))return null;try{return JSON.parse(po(t,"utf8"))}catch{return null}}function Lo(e,t){fo(Je(e),JSON.stringify(t),"utf8");}function Ao(e){try{ho(Je(e));}catch{}}an.exports={loadState:Oo,saveState:Lo,deleteState:Ao};});var ze=d((Ia,ln)=>{var{readFileSync:cn,existsSync:un}=c("fs");function Io(e){if(!e||!un(e))return null;try{let t=cn(e,"utf8").trimEnd().split(`
|
|
85
85
|
`);for(let n=t.length-1;n>=0;n--)try{let s=JSON.parse(t[n]);if(s.type==="user"&&s.uuid)return s.uuid}catch{}}catch{}return null}function ko(e){if(!e||!un(e))return null;try{let t=cn(e,"utf8").trimEnd().split(`
|
|
86
86
|
`),n=[],s=0,o=0,r=!1;for(let i=t.length-1;i>=0;i--)try{let a=JSON.parse(t[i]);if(a.type==="user"){if(r)break;continue}if(a.type==="assistant"){r=!0;let l=(a.message?.content??[]).filter(h=>h.type==="text").map(h=>h.text).join("");l&&n.unshift(l);let u=a.message?.usage??{};s+=(u.input_tokens??0)+(u.cache_read_input_tokens??0)+(u.cache_creation_input_tokens??0),o+=u.output_tokens??0;}}catch{}return !n.length&&s===0?null:{text:n.join(`
|
|
87
87
|
|
|
88
|
-
`),inputTokens:s,outputTokens:o}}catch{}return null}ln.exports={readPromptUuid:Io,readLastAssistantOutput:ko};});var
|
|
88
|
+
`),inputTokens:s,outputTokens:o}}catch{}return null}ln.exports={readPromptUuid:Io,readLastAssistantOutput:ko};});var _e=d((ka,hn)=>{var{readFileSync:No,existsSync:dn,readdirSync:Co}=c("fs"),{homedir:pn}=c("os"),{join:G,extname:bo}=c("path"),Uo=new Set([".venv","__pycache__",".git","node_modules"]),vo=new Set([".pyc",".pyo"]),Ro=new Set(["SKILL.md",".DS_Store",".gitignore"]);function Po(e,t){if(!e)return null;let n=[G(pn(),".claude","skills",e,"SKILL.md"),G(t||"",".claude","skills",e,"SKILL.md")];for(let s of n)if(dn(s))try{return No(s,"utf8")}catch{}return null}function $o(e){return e.match(/^\/([a-z][a-z0-9-]*)(?:\s.*)?$/i)?.[1]||null}var fn=new Set(["Read","Write","Edit","MultiEdit","Bash","Glob","Grep","TodoWrite","WebFetch","WebSearch","Agent","Task"]);function qo(e){return !!e.slashSkill||e.toolCalls.some(s=>s.tool==="Skill")?e.toolCalls.some(s=>fn.has(s.tool))?"complete":"prerequisite_required":null}function Fo(e,t){if(!e)return null;let n=[G(pn(),".claude","skills",e),G(t||"",".claude","skills",e)],s=null;for(let i of n)if(dn(G(i,"SKILL.md"))){s=i;break}if(!s)return null;let o=[];function r(i,a){for(let p of Co(i,{withFileTypes:true})){if(Uo.has(p.name)||Ro.has(p.name)||vo.has(bo(p.name)))continue;let l=a?`${a}/${p.name}`:p.name;p.isDirectory()?r(G(i,p.name),l):o.push(l);}}return r(s,""),o.length>0?o:null}hn.exports={readSkillContent:Po,readSkillArtifacts:Fo,detectSlashSkill:$o,EXECUTION_TOOLS:fn,detectExecutionStatus:qo};});var Tn=d((Na,En)=>{var{generateTraceId:Sn,generateSpanId:xo,nowNs:Mo}=re(),{saveState:Bo}=oe(),{readPromptUuid:Do}=ze(),{detectSlashSkill:Go,readSkillContent:jo,readSkillArtifacts:Vo}=_e(),{passthrough:Yo}=D(),{dbg:Wo}=N(),{ENV:Ho}=w();async function Ko(e){let t=e.session_id||"unknown",n=e.prompt||"",s=e.cwd||"",o=Do(e.transcript_path)||Sn(),r=Go(n),i=r?jo(r,s):null,a=r?Vo(r,s):null;Bo(t,{traceId:Sn(),spanId:xo(),startNs:Mo(),sessionId:t,prompt:n,cwd:s,traceName:o,transcriptPath:e.transcript_path||"",model:process.env[Ho.ANTHROPIC_MODEL]||"",toolCalls:[],spans:[],pendingTool:null,slashSkill:r,skillContent:i,skillArtifacts:a}),Wo("UserPromptSubmit",`sid=${t}`,`traceName=${o}`,`slashSkill=${r}`),Yo(e);}En.exports={onUserPromptSubmit:Ko};});var gn=d((Ca,wn)=>{var{nowNs:Jo}=re(),{loadState:zo,saveState:Xo}=oe(),{truncate:Zo,passthrough:Qo}=D(),{dbg:ei}=N(),{TRACE_LIMITS:ti}=w();async function ni(e){let t=e.session_id||"unknown",n=e.tool_name||"unknown",s=e.tool_input||{},o=zo(t);o&&(o.pendingTool={name:n,inputStr:Zo(s,ti.TOOL_INPUT),startNs:Jo()},Xo(t,o)),ei("PreToolUse",`sid=${t}`,`tool=${n}`,`stateFound=${!!o}`),Qo(e);}wn.exports={onPreToolUse:ni};});var yn=d((ba,mn)=>{var si=c("https"),ri=c("http"),{FLOW_URLS:oi}=w();function ii(e){let t=new URL(e),n=new URL(oi.GATEWAY_HEALTH);return n.hostname=t.hostname,n.port=t.port,n.protocol=t.protocol,n}function _n(e,t){return new Promise((n,s)=>{let r=(e._isSSL?si:ri).request(e,i=>{let a=[];i.on("data",p=>a.push(p)),i.on("end",()=>n({statusCode:i.statusCode,body:a.join("")}));});r.on("error",i=>s(new Error(`Network error: ${i.message}`))),t&&r.write(t),r.end();})}async function ai(e){let t;try{t=ii(e);}catch{return false}let n=t.protocol==="https:";try{let s=await _n({hostname:t.hostname,port:t.port||(n?443:80),path:t.pathname,method:"GET",_isSSL:n},null);return s.statusCode>=200&&s.statusCode<300}catch{return false}}async function ci(e,t,n){let s=JSON.stringify(e),o=new URL(t),r=o.protocol==="https:",i=String(n).replace(/[\r\n]/g,"");try{return (await _n({hostname:o.hostname,port:o.port||(r?443:80),path:o.pathname,method:"POST",headers:{"Content-Type":"application/json",Authorization:i,"Content-Length":Buffer.byteLength(s)},_isSSL:r},s)).statusCode}catch{return 0}}mn.exports={checkHealth:ai,sendTraces:ci};});var In=d((Ua,An)=>{var C=c("fs"),Xe=c("path"),On=c("os"),{BUFFER:ie}=w(),{dbg:ae}=N();function Ln(e){if(/[/\\]/.test(e))throw new Error(`Invalid buffer fileId: ${e}`);return Xe.join(On.tmpdir(),`${ie.FILE_PREFIX}${e}.json`)}function Ze(){let e=On.tmpdir(),t;try{t=C.readdirSync(e);}catch{return []}return t.filter(n=>n.startsWith(ie.FILE_PREFIX)&&n.endsWith(".json")).map(n=>{let s=Xe.join(e,n),o=0;try{o=C.statSync(s).mtimeMs;}catch{}return {full:s,mtime:o}}).sort((n,s)=>n.mtime-s.mtime).map(n=>n.full)}function ui(e){try{let t=Ze();if(t.length>=ie.MAX_FILES){let o=t.slice(0,t.length-ie.MAX_FILES+1);for(let r of o)try{C.unlinkSync(r);}catch{}}let n=`${Date.now()}-${Math.random().toString(36).slice(2,8)}`,s={fileId:n,bufferedAt:Date.now(),payload:e};return C.writeFileSync(Ln(n),JSON.stringify(s),"utf8"),ae("buffer",`saved fileId=${n}`),n}catch(t){return ae("buffer",`saveToBuffer failed: ${t.message}`),null}}function li(){let e=Ze(),t=[];for(let n of e)try{let s=C.readFileSync(n,"utf8"),o=JSON.parse(s);o&&o.fileId&&o.payload&&t.push(o);}catch{ae("buffer",`skipping malformed file: ${n}`);}return t}function di(e){try{C.unlinkSync(Ln(e)),ae("buffer",`deleted fileId=${e}`);}catch{}}function pi(){let e=Ze(),t=Date.now()-ie.MAX_AGE_MS;for(let n of e)try{let{mtimeMs:s}=C.statSync(n);s<t&&(C.unlinkSync(n),ae("buffer",`evicted stale: ${Xe.basename(n)}`));}catch{}}An.exports={saveToBuffer:ui,loadBuffer:li,deleteBuffer:di,cleanStaleBuffers:pi};});var Qe=d((va,bn)=>{var{resolveCredentials:fi}=ne(),{OTLP:kn}=w(),{dbg:j}=N(),{checkHealth:hi,sendTraces:Cn}=yn(),{saveToBuffer:Nn,loadBuffer:Si,deleteBuffer:Ei,cleanStaleBuffers:Ti}=In(),wi={name:kn.SCOPE_NAME,version:kn.SCOPE_VERSION},gi={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 _i(e,t){return t==null||t===""?null:{key:e,value:{stringValue:String(t)}}}function mi(...e){return e.filter(Boolean)}function yi(e,t){return {resourceSpans:[{resource:{attributes:e},scopeSpans:[{scope:wi,spans:Array.isArray(t)?t:[t]}]}]}}function Oi(e,t){return new Promise(n=>{let s=JSON.stringify(e),o=new URL(t.endpoint),r=o.protocol==="https:",i=u=>String(u).replace(/[\r\n]/g,""),a={hostname:o.hostname,port:o.port||(r?443:80),path:o.pathname,method:"POST",headers:{"Content-Type":"application/json",Authorization:i(t.authHeader),"Content-Length":Buffer.byteLength(s)}},l=(r?c("https"):c("http")).request(a,u=>{u.resume(),n(u.statusCode);});l.on("error",()=>n(0)),l.write(s),l.end();})}async function Li(e){Ti();let t=Si();if(t.length){j("replayBufferedTraces",`replaying ${t.length} buffered trace(s)`);for(let n of t)try{let s=await Cn(n.payload,e.endpoint,e.authHeader);s>=200&&s<300?(Ei(n.fileId),j("replayBufferedTraces",`replayed fileId=${n.fileId} status=${s}`)):j("replayBufferedTraces",`replay failed fileId=${n.fileId} status=${s}`);}catch(s){j("replayBufferedTraces",`replay error fileId=${n.fileId}: ${s.message}`);}}}async function Ai(e){let t=await fi();return t.length?(await Promise.all(t.map(async s=>s.mode==="gateway"?await hi(s.endpoint)?(await Li(s),Cn(e,s.endpoint,s.authHeader)):(j("postToLangfuse","gateway health check failed \u2014 buffering trace"),Nn(e),0):Oi(e,s)))).find(s=>s!==0)||0:(t.authError&&(j("postToLangfuse","auth refresh failed \u2014 buffering trace"),Nn(e)),0)}bn.exports={LF:gi,a:_i,attrs:mi,buildPayload:yi,postToLangfuse:Ai};});var et=d((Ra,Un)=>{var _="[REDACTED]",Ii=[{re:/\b(sk-[A-Za-z0-9_\-]{20,})/g,replace:()=>`sk-${_}`},{re:/\b(pk-[A-Za-z0-9_\-]{20,})/g,replace:()=>`pk-${_}`},{re:/\b(Bearer\s+)[A-Za-z0-9\-._~+/]+=*/gi,replace:(e,t)=>`${t}${_}`},{re:/\b(Basic\s+)[A-Za-z0-9+/]+=*/gi,replace:(e,t)=>`${t}${_}`},{re:/(-----BEGIN [A-Z ]+-----)[^-]*(-----END [A-Z ]+-----)/g,replace:(e,t,n)=>`${t}
|
|
89
89
|
${_}
|
|
90
|
-
${n}`},{re:/\b(AKIA[0-9A-Z]{16})\b/g,replace:()=>`AKIA${_}`},{re:/(aws_secret_access_key\s*[=:]\s*)([A-Za-z0-9/+]{40})/gi,replace:(e,t)=>`${t}${_}`},{re:/\b(ghp_[A-Za-z0-9]{36,})/g,replace:()=>`ghp_${_}`},{re:/\b(github_pat_[A-Za-z0-9_]{36,})/gi,replace:()=>`github_pat_${_}`},{re:/\b(eyJ[A-Za-z0-9_\-]+\.eyJ[A-Za-z0-9_\-]+\.[A-Za-z0-9_\-]+)/g,replace:()=>`eyJ.${_}`},{re:/\b([A-Z0-9_]*(?:SECRET|TOKEN|KEY|PASSWORD|PASSWD|PWD|CREDENTIAL|API)[A-Z0-9_]*\s*=\s*)(['"]?)([^\s'"#\n]+)\2/gi,replace:(e,t,n)=>`${t}${n}${_}${n}`},{re:/([a-z][a-z0-9+\-.]*:\/\/[^:/?#\s]*):([^@\s]+)@/gi,replace:(e,t)=>`${t}:${_}@`}];function ki(e){if(e==null)return "";let t=typeof e=="string"?e:JSON.stringify(e);return Ii.reduce((n,{re:s,replace:o})=>n.replace(s,o),t)}Un.exports={sanitize:ki,REDACTED:_};});var xn=d((Pa,Fn)=>{var{generateSpanId:Ni,nowNs:Ci}=
|
|
91
|
-
`)),h=a?.inputTokens??0,E=a?.outputTokens??0,m=s.toolCalls.map((S,
|
|
90
|
+
${n}`},{re:/\b(AKIA[0-9A-Z]{16})\b/g,replace:()=>`AKIA${_}`},{re:/(aws_secret_access_key\s*[=:]\s*)([A-Za-z0-9/+]{40})/gi,replace:(e,t)=>`${t}${_}`},{re:/\b(ghp_[A-Za-z0-9]{36,})/g,replace:()=>`ghp_${_}`},{re:/\b(github_pat_[A-Za-z0-9_]{36,})/gi,replace:()=>`github_pat_${_}`},{re:/\b(eyJ[A-Za-z0-9_\-]+\.eyJ[A-Za-z0-9_\-]+\.[A-Za-z0-9_\-]+)/g,replace:()=>`eyJ.${_}`},{re:/\b([A-Z0-9_]*(?:SECRET|TOKEN|KEY|PASSWORD|PASSWD|PWD|CREDENTIAL|API)[A-Z0-9_]*\s*=\s*)(['"]?)([^\s'"#\n]+)\2/gi,replace:(e,t,n)=>`${t}${n}${_}${n}`},{re:/([a-z][a-z0-9+\-.]*:\/\/[^:/?#\s]*):([^@\s]+)@/gi,replace:(e,t)=>`${t}:${_}@`}];function ki(e){if(e==null)return "";let t=typeof e=="string"?e:JSON.stringify(e);return Ii.reduce((n,{re:s,replace:o})=>n.replace(s,o),t)}Un.exports={sanitize:ki,REDACTED:_};});var xn=d((Pa,Fn)=>{var{generateSpanId:Ni,nowNs:Ci}=re(),{loadState:bi,saveState:Ui}=oe(),{LF:ce,a:v,attrs:vi}=Qe(),{truncate:vn,firstLine:Ri,passthrough:Rn}=D(),{readSkillContent:Pi,readSkillArtifacts:$i}=_e(),{dbg:Pn}=N(),{TRACE_LIMITS:$n}=w(),{sanitize:qn}=et();async function qi(e){let t=e.session_id||"unknown",n=e.tool_name||"unknown",s=e.tool_input||{},o=e.tool_response||"",r=bi(t);if(!r){Rn(e);return}let i=Ci(),a=r.pendingTool?.name===n,p=a?r.pendingTool.startNs:String(BigInt(i)-200000000n),l=a?r.pendingTool.inputStr:vn(s,$n.TOOL_INPUT),u=l;if(n==="Skill"){let b=typeof s=="object"&&s!==null?s.skill||s.name||s.skillName||String(Object.values(s)[0]??""):String(s),I=b?Pi(b.trim(),r.cwd):null;I&&(u=I,r.skillContent||(r.skillContent=I),r.slashSkill||(r.slashSkill=b.trim()),r.skillArtifacts||(r.skillArtifacts=$i(b.trim(),r.cwd))),Pn("PostToolUse","Skill tool detected",`skillName=${b}`,`contentFound=${!!I}`);}let h=qn(vn(o,$n.TOOL_OUTPUT)),E=/\b(error|exception|failed|failure|traceback|errno)\b/i.test(h.slice(0,500)),m=E?"ERROR":"DEFAULT",V=Ni(),de=Math.round(Number(BigInt(i)-BigInt(p))/1e6),Le={Agent:"AGENT",Task:"AGENT"}[n]??"TOOL";r.toolCalls.push({tool:n,brief:Ri(l,60),error:E,durationMs:de}),r.spans.push({traceId:r.traceId,spanId:V,parentSpanId:r.spanId,name:n,kind:3,startTimeUnixNano:p,endTimeUnixNano:i,attributes:vi(v(ce.OBS_NAME,n),v(ce.OBS_TYPE,Le),v(ce.OBS_LEVEL,m),v(ce.OBS_INPUT,qn(u)),v(ce.OBS_OUTPUT,h),v("tool.name",n),v("tool.error",String(E))),status:{code:E?2:1}}),r.pendingTool=null,Ui(t,r),Pn("PostToolUse",`sid=${t}`,`tool=${n}`,`error=${E}`,`durationMs=${de}`,`totalSpans=${r.spans.length}`),Rn(e);}Fn.exports={onPostToolUse:qi};});var Bn=d(($a,Mn)=>{var tt={"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 Fi(e,t,n){let s=Object.keys(tt).find(i=>(e||"").toLowerCase().includes(i));if(!s)return;let o=tt[s],r=(t*o.input+n*o.output)/1e6;return Math.round(r*1e6)/1e6}Mn.exports={MODEL_PRICING:tt,calcCostUsd:Fi};});var Yn=d((qa,Vn)=>{var{generateSpanId:Dn,nowNs:xi}=re(),{loadState:Mi,deleteState:Gn}=oe(),{LF:T,a:f,attrs:me,buildPayload:Bi,postToLangfuse:Di}=Qe(),{getIdentityFromToken:Gi}=ne(),{calcCostUsd:ji}=Bn(),{readLastAssistantOutput:Vi}=ze(),{truncate:ye,firstLine:Yi,passthrough:nt}=D(),{dbg:ue}=N(),{detectExecutionStatus:Wi}=_e(),{sanitize:jn}=et(),{TRACE_LIMITS:Oe}=w();async function Hi(e){let t=e.session_id||"unknown",n=e.stop_reason||"end_turn",s=Mi(t);if(!s){nt(e);return}let o=xi(),r=await Gi();if(s.slashSkill&&!s.toolCalls.some(S=>S.tool==="Skill")){let S=Dn(),Y=s.skillContent?s.skillContent:JSON.stringify({skill:s.slashSkill});s.toolCalls.push({tool:"Skill",brief:s.slashSkill,error:false,durationMs:0,synthetic:true}),s.spans.push({traceId:s.traceId,spanId:S,parentSpanId:s.spanId,name:"Skill",kind:3,startTimeUnixNano:s.startNs,endTimeUnixNano:s.startNs,attributes:me(f(T.OBS_NAME,"Skill"),f(T.OBS_TYPE,"TOOL"),f(T.OBS_LEVEL,"DEFAULT"),f(T.OBS_INPUT,Y),f(T.OBS_OUTPUT,"loaded via slash command"),f("tool.name","Skill"),f("tool.error","false"),f("skill.name",s.slashSkill),f("skill.invocation","slash-command")),status:{code:1}}),ue("Stop",`slashSkill=${s.slashSkill}`,"synthetic span injected");}let i=e.transcript_path||s.transcriptPath||"",a=Vi(i),p=s.toolCalls.length,l=s.toolCalls.filter(S=>S.error).length,u=jn(a?.text?ye(a.text,Oe.TRACE_OUTPUT):p===0?"No tools used":s.toolCalls.map((S,Y)=>`${Y+1}. ${S.tool}${S.brief?` \u2192 ${S.brief}`:""}${S.error?" [ERROR]":""}`).join(`
|
|
91
|
+
`)),h=a?.inputTokens??0,E=a?.outputTokens??0,m=s.toolCalls.map((S,Y)=>`${Y+1}. ${S.tool}${S.brief?` \u2192 ${S.brief}`:""}${S.error?" [ERROR]":""} (${S.durationMs}ms)`),V=!!(s.slashSkill||s.toolCalls.some(S=>S.tool==="Skill")),de=s.toolCalls.some(S=>S.tool==="Agent");if(!V&&!de){ue("Stop",`sid=${t}`,"skipping trace \u2014 no Skill or Agent calls found"),Gn(t),nt(e);return}let pe=V?"skill":"agent",Le=Math.round(Number(BigInt(o)-BigInt(s.startNs))/1e6),b=ji(s.model,h,E),I=Wi(s);I==="prerequisite_required"&&(s.spans.push({traceId:s.traceId,spanId:Dn(),parentSpanId:s.spanId,name:"prerequisite-check",kind:3,startTimeUnixNano:s.startNs,endTimeUnixNano:o,attributes:me(f(T.OBS_NAME,"prerequisite-check"),f(T.OBS_TYPE,"EVENT"),f(T.OBS_LEVEL,"WARNING"),f(T.OBS_OUTPUT,u),f("skill.name",s.slashSkill||void 0),f("execution_status","prerequisite_required")),status:{code:1}}),ue("Stop",`sid=${t}`,"prerequisite-check span injected",`skill=${s.slashSkill}`));let st=(()=>{if(!(!V||!s.prompt)){if(s.slashSkill){let S=s.prompt.replace(new RegExp(`^\\/${s.slashSkill}\\s*`,"i"),"").trim();return S?ye(S,Oe.USER_INSTRUCTION):void 0}return ye(s.prompt,Oe.USER_INSTRUCTION)||void 0}})(),Hn=JSON.stringify({trace_type:pe,...I!==null&&{execution_status:I},...s.slashSkill&&{skill_name:s.slashSkill},...s.skillArtifacts?.length&&{skill_artifacts:s.skillArtifacts},...st!==void 0&&{user_instruction:st},latency_ms:Le,...h&&{tokens_input:h},...E&&{tokens_output:E},cost_usd:b,...s.model&&{model:s.model},toolCount:p,errorCount:l,stopReason:n,sessionId:s.sessionId,tools:m.length?m:void 0}),Kn=jn(ye(s.prompt,Oe.TRACE_INPUT)),Jn=me(f(T.TRACE_NAME,s.traceName),f(T.TRACE_INPUT,Kn),f(T.TRACE_OUTPUT,u),f(T.TRACE_METADATA,Hn),f(T.SESSION_ID,s.sessionId),f(T.USER_ID,r.user),f(T.OBS_TYPE,"GENERATION"),f(T.MODEL,s.model),h?f(T.INPUT_TOKENS,h):null,E?f(T.OUTPUT_TOKENS,E):null,f("claude.stop_reason",n),f("claude.tool_count",String(p)),f("claude.error_count",String(l)),f("claude.session_id",s.sessionId),f("flow.trace_type",pe),{key:T.TRACE_TAGS,value:{arrayValue:{values:[{stringValue:pe}]}}}),zn={traceId:s.traceId,spanId:s.spanId,name:s.traceName,kind:1,startTimeUnixNano:s.startNs,endTimeUnixNano:o,attributes:Jn,status:{code:l>0?2:1}},Xn=me(f("service.name",process.env.LANGFUSE_PROJECT_NAME||"claude-code"),f("deployment.environment",process.env.LANGFUSE_ENVIRONMENT||"default")),rt=[...s.spans||[],zn];ue("Stop",`sid=${t}`,`totalTools=${p}`,`errorTools=${l}`,`spans=${rt.length}`,`inputTokens=${h}`,`outputTokens=${E}`,`traceOutput="${Yi(u,80)}"`);let Zn=await Di(Bi(Xn,rt));ue("Stop",`POST status=${Zn}`,`traceId=${s.traceId}`),Gn(t),nt(e);}Vn.exports={onStop:Hi};});var Wn=d(()=>{var{credentialsAvailable:Ki}=ne(),{readInput:Ji}=D(),{onUserPromptSubmit:zi}=Tn(),{onPreToolUse:Xi}=gn(),{onPostToolUse:Zi}=xn(),{onStop:Qi}=Yn();async function ea(){let e=process.argv[2];if(!await Ki()){let n=[];process.stdin.on("data",s=>n.push(s)),process.stdin.on("end",()=>process.stdout.write(n.join("")));return}let t=await Ji();switch(e){case "UserPromptSubmit":await zi(t);break;case "PreToolUse":await Xi(t);break;case "PostToolUse":await Zi(t);break;case "Stop":await Qi(t);break;default:process.stderr.write(`[flow-obs] unknown event: ${e}
|
|
92
92
|
`),process.stdout.write(JSON.stringify(t));}}ea().catch(e=>{process.stderr.write(`[flow-obs] fatal: ${e.message}
|
|
93
|
-
`),process.exit(0);});});var ta=new Set(["UserPromptSubmit","PreToolUse","PostToolUse","Stop"]),[,,
|
|
94
|
-
`),process.exit(
|
|
93
|
+
`),process.exit(0);});});var ta=new Set(["UserPromptSubmit","PreToolUse","PostToolUse","Stop"]),[,,A,le]=process.argv;if(A==="--version"||A==="-v"){let{version:e}=fe();process.stdout.write(e+`
|
|
94
|
+
`),process.exit(0);}else if(A==="--help"||A==="-h"){let{bold:e,cyan:t,dim:n}=W(),{version:s}=fe();process.stdout.write(`
|
|
95
|
+
`+e(" flow-ai-obs")+n(" v"+s)+`
|
|
96
|
+
|
|
97
|
+
`),process.stdout.write(t(" install")+n(` Register Claude Code hooks in ~/.claude/settings.json
|
|
98
|
+
`)),process.stdout.write(t(" auth login")+n(` Authenticate with Flow (clientId / clientSecret / tenant)
|
|
99
|
+
`)),process.stdout.write(t(" auth logout")+n(` Remove credentials
|
|
100
|
+
`)),process.stdout.write(t(" auth status")+n(` Show current auth status
|
|
101
|
+
`)),process.stdout.write(t(" check")+n(` Validate full observability setup
|
|
102
|
+
|
|
103
|
+
`)),process.stdout.write(n(` Flags: --version, -v Show version
|
|
104
|
+
`)),process.stdout.write(n(` --help, -h Show this help
|
|
105
|
+
|
|
106
|
+
`)),process.stdout.write(n(` (Hook events: UserPromptSubmit | PreToolUse | PostToolUse | Stop)
|
|
107
|
+
|
|
108
|
+
`)),process.exit(0);}else if(A==="install"){ke().checkForUpdate();let{runInstall:e}=Bt();e().then(t=>process.exit(t)).catch(t=>{process.stderr.write(`Unexpected error: ${t.message}
|
|
109
|
+
`),process.exit(1);});}else if(A==="auth"){ke().checkForUpdate();let{runLogin:e,runLogout:t,runStatus:n}=Ht();(async()=>{let s=0;if(le==="login"||!le){let o=process.argv.slice(4),r=i=>{let a=o.indexOf(i);return a!==-1?o[a+1]:void 0};s=await e({clientId:r("--client-id"),clientSecret:r("--client-secret"),tenant:r("--tenant")});}else if(le==="logout"){let o=process.argv.includes("--force");s=await t(o);}else le==="status"?s=await n():(process.stderr.write(`Unknown auth subcommand: ${le}
|
|
95
110
|
`),process.stderr.write(`Usage: flow-ai-obs auth [login|logout|status]
|
|
96
|
-
`),s=1);process.exit(s);})();}else if(
|
|
97
|
-
`),process.exit(1);});}else if(ta.has(
|
|
111
|
+
`),s=1);process.exit(s);})();}else if(A==="otel-headers"){let{runOtelHeaders:e}=Jt();e().then(t=>process.exit(t)).catch(()=>process.exit(1));}else if(A==="check"){let{runCheck:e}=tn();e().then(t=>process.exit(t)).catch(t=>{process.stderr.write(`Unexpected error: ${t.message}
|
|
112
|
+
`),process.exit(1);});}else if(ta.has(A))Wn();else {let{bold:e,cyan:t,dim:n}=W();process.stdout.write(`
|
|
98
113
|
`+e(" flow-ai-obs")+`
|
|
99
114
|
|
|
100
115
|
`),process.stdout.write(t(" install")+n(` Register Claude Code hooks in ~/.claude/settings.json
|