Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: modify Jira tool for API key support #396

Merged
merged 1 commit into from
Jan 31, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion atlassian/credential/tool.gpt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ Name: Atlassian OAuth Credential
Share Credential: ../../oauth2 as atlassian
with ATLASSIAN_OAUTH_TOKEN as token and
atlassian as integration and
ATLASSIAN_OAUTH_TOKEN as prompt_tokens and
ATLASSIAN_API_TOKEN as prompt_tokens and
ATLASSIAN_EMAIL;ATLASSIAN_SITE_URL as prompt_vars and
"offline_access
read:me
read:account
Expand Down
31 changes: 26 additions & 5 deletions atlassian/jira/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,49 @@ const command = process.argv[2]
async function main() {

try {
if (!process.env.ATLASSIAN_OAUTH_TOKEN) {
throw new Error("ATLASSIAN_OAUTH_TOKEN is required")
if (!process.env.ATLASSIAN_OAUTH_TOKEN && (!process.env.ATLASSIAN_API_TOKEN || !process.env.ATLASSIAN_EMAIL || !process.env.ATLASSIAN_SITE_URL)) {
throw new Error("ATLASSIAN_OAUTH_TOKEN or all of ATLASSIAN_API_TOKEN, ATLASSIAN_EMAIL, and ATLASSIAN_SITE_URL are required")
}

let authType = "Bearer"
let authToken = process.env.ATLASSIAN_OAUTH_TOKEN
if (process.env.ATLASSIAN_API_TOKEN) {
authType = "Basic"
authToken = Buffer.from(`${process.env.ATLASSIAN_EMAIL}:${process.env.ATLASSIAN_API_TOKEN.trim()}`).toString("base64")
}

let baseUrl
if (command !== 'listJiraSites') {
if (!process.env.SITE_ID) {
if (process.env.ATLASSIAN_SITE_URL) {
baseUrl = process.env.ATLASSIAN_SITE_URL
if (baseUrl.endsWith('/')) {
baseUrl = baseUrl.slice(0, -1)
}
if (!baseUrl.startsWith('http://') && !baseUrl.startsWith('https://')) {
baseUrl = `https://${baseUrl}`
}
baseUrl = `${baseUrl}/rest/api/3`
} else if (process.env.SITE_ID) {
baseUrl = `https://api.atlassian.com/ex/jira/${process.env.SITE_ID}/rest/api/3`
} else {
throw new Error('site_id argument not provided')
}
baseUrl = `https://api.atlassian.com/ex/jira/${process.env.SITE_ID}/rest/api/3`
}
const client = axios.create({
baseURL: baseUrl,
headers: {
'Authorization': `Bearer ${process.env.ATLASSIAN_OAUTH_TOKEN}`,
'Authorization': `${authType} ${authToken}`,
'Accept': 'application/json',
},
})

let result = null
switch (command) {
case "listJiraSites":
if (process.env.ATLASSIAN_SITE_URL) {
console.log("listJiraSites is not needed when ATLASSIAN_SITE_URL is set, so you can continue without needing the site_id argument")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we just return the first component of the subdomain here instead? The side_id argument is ignored when a PAT credential is used, so it won't matter if it's not a real Jira ID, and we won't need to add the additional line context (and hope the LLM will respect it).

IMO, the only thing that could interfere with that is if the LLM has info about Jira site IDs in its training set and gets confused by the dummy ID. Although, I think it's pretty unlikely given how explicit our tool definitions and context is wrt site_id usage.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does that provide some value?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just that it depends less on the LLM doing the right thing based on the context. I've been bitten by that before, especially when a bunch of tools are added to an agent and the context grows large.

break
}
result = await listJiraSites(client)
break
case "createIssue":
Expand Down
1 change: 1 addition & 0 deletions atlassian/jira/tool.gpt
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ If you don't know what Jira Sites are available for the current user, call the L
to get the list of sites that the user has access to.
Tools that require a site_id must be called with a site_id from the Jira Sites that are available for the current user.
When it's unclear which Jira Site a user is referring to, always ask the user to select a site before calling a tool that requires a site_id argument.
When using the Jira Sites tool, it may tell you that you don't need a site_id. If it does, then that's great and you can move along without it.
When information about the current user is needed to fulfill a request, call the Get Current User tool for the applicable Jira Sites.
Always call Get Project to gather more information about a Project when prompted to interact with the issues in a project.
Issue descriptions are always in ADF (Atlassian Document Format) and must be passed as a JSON string when calling the Create Issue tool.
Expand Down