33// Licensed under the Apache License, Version 2.0
44// https://www.apache.org/licenses/LICENSE-2.0
55
6+ import { execFileSync } from "node:child_process" ;
67import { readFileSync } from "node:fs" ;
78import path from "node:path" ;
89import process from "node:process" ;
@@ -24,17 +25,52 @@ const forceDisabled =
2425const forceEnabled =
2526 env ( "JF_AGENT_GUARD_FORCE_ENABLE" ) === "true" ;
2627
27- async function isAgentGuardEnabledViaSettings ( ) {
28+ // Resolve {baseUrl, token} from env vars, falling back to the JFrog CLI's
29+ // default server. Returns null when nothing resolves.
30+ function resolveCredentials ( ) {
2831 const baseUrl = env ( "JFROG_URL" , "JF_URL" ) ;
2932 const token = env ( "JFROG_ACCESS_TOKEN" , "JF_ACCESS_TOKEN" ) ;
30- if ( ! baseUrl ) {
31- debug ( "JFROG_URL/JF_URL is not set; skipping settings check " ) ;
32- return false ;
33+ if ( baseUrl && token ) {
34+ debug ( "Resolved credentials from environment variables " ) ;
35+ return { baseUrl , token } ;
3336 }
34- if ( ! token ) {
35- debug ( "JFROG_ACCESS_TOKEN/JF_ACCESS_TOKEN is not set; skipping settings check" ) ;
37+
38+ // `jf config export` emits the default server as a base64-encoded JSON token.
39+ let configToken ;
40+ try {
41+ configToken = execFileSync ( "jf" , [ "config" , "export" ] , {
42+ encoding : "utf8" ,
43+ stdio : [ "ignore" , "pipe" , "ignore" ] ,
44+ } ) . trim ( ) ;
45+ } catch ( error ) {
46+ debug ( `'jf config export' failed (jf not on PATH or no server configured): ${ error . message } ` ) ;
47+ return null ;
48+ }
49+
50+ let cfg ;
51+ try {
52+ cfg = JSON . parse ( Buffer . from ( configToken , "base64" ) . toString ( "utf8" ) ) ;
53+ } catch ( error ) {
54+ debug ( `Could not decode the jf Config Token: ${ error . message } ` ) ;
55+ return null ;
56+ }
57+
58+ if ( ! cfg ?. url || ! cfg ?. accessToken ) {
59+ debug ( "jf Config Token did not contain a usable url + accessToken" ) ;
60+ return null ;
61+ }
62+
63+ debug ( `Resolved credentials via 'jf config export' (serverId: ${ cfg . serverId ?? "<unknown>" } )` ) ;
64+ return { baseUrl : cfg . url , token : cfg . accessToken } ;
65+ }
66+
67+ async function isAgentGuardEnabledViaSettings ( ) {
68+ const credentials = resolveCredentials ( ) ;
69+ if ( ! credentials ) {
70+ debug ( "No JFrog credentials resolved; skipping settings check" ) ;
3671 return false ;
3772 }
73+ const { baseUrl, token } = credentials ;
3874
3975 const url =
4076 baseUrl . replace ( / \/ + $ / , "" ) +
@@ -92,13 +128,17 @@ try {
92128 path . join ( root , "templates" , "jfrog-mcp-management.md" ) ,
93129 "utf8" ,
94130 ) ;
95- } catch {
96- process . stdout . write ( "{}" ) ;
131+ } catch ( error ) {
132+ debug ( `Could not read instructions template: ${ error . message } ` ) ;
97133 process . exit ( 0 ) ;
98134}
99135
136+ // The IDE consumes hookSpecificOutput.additionalContext from a SessionStart hook.
100137process . stdout . write (
101138 JSON . stringify ( {
102- additional_context : template ,
139+ hookSpecificOutput : {
140+ hookEventName : "SessionStart" ,
141+ additionalContext : template ,
142+ } ,
103143 } ) ,
104144) ;
0 commit comments