Skip to content
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- `send_slack_message` (data sink)
- `create_workflow_for_notification` (potentially destructive)
- `make_workflow_public` (potentially destructive)
- Added error handling for environments where Davis Copilot is not enabled, providing a link to enable it via logs

## 0.6.1

Expand Down
22 changes: 22 additions & 0 deletions src/capabilities/davis-copilot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,28 @@ import {
// Re-export types that are used externally
export type { Dql2NlResponse };

// Documentation links for Davis Copilot
export const DAVIS_COPILOT_DOCS = {
ENABLE_COPILOT:
'https://docs.dynatrace.com/docs/discover-dynatrace/platform/davis-ai/copilot/copilot-getting-started#enable-davis-copilot',
} as const;

/**
* Check if a specific Davis Copilot skill is available
* Returns true if the skill is available, false otherwise
*/
export const isDavisCopilotSkillAvailable = async (dtClient: HttpClient, skill: string): Promise<boolean> => {
try {
const client = new PublicClient(dtClient);
const response = await client.listAvailableSkills();
const availableSkills = response.skills || [];
return availableSkills.includes(skill as any);
} catch (error: any) {
// If Davis Copilot is not enabled or any other error occurs, return false
return false;
}
};

/**
* Generate DQL from natural language
* Converts plain English descriptions into powerful Dynatrace Query Language (DQL) statements.
Expand Down
21 changes: 21 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ import {
chatWithDavisCopilot,
explainDqlInNaturalLanguage,
generateDqlFromNaturalLanguage,
isDavisCopilotSkillAvailable,
DAVIS_COPILOT_DOCS,
} from './capabilities/davis-copilot';
import { DynatraceEnv, getDynatraceEnv } from './getDynatraceEnv';
import { createTelemetry, Telemetry } from './utils/telemetry-openkit';
Expand Down Expand Up @@ -101,6 +103,7 @@ function handleClientRequestError(error: ClientRequestError): string {
additionalErrorInformation =
'Note: Your user or service-user is most likely lacking the necessary permissions/scopes for this API Call.';
}

return `Client Request Error: ${error.message} with HTTP status: ${error.response.status}. ${additionalErrorInformation} (body: ${JSON.stringify(error.body)})`;
}

Expand Down Expand Up @@ -711,6 +714,12 @@ const main = async () => {
dtPlatformToken,
);

// Check if the nl2dql skill is available
const isAvailable = await isDavisCopilotSkillAvailable(dtClient, 'nl2dql');
if (!isAvailable) {
return `❌ The DQL generation skill is not available. Please visit: ${DAVIS_COPILOT_DOCS.ENABLE_COPILOT}`;
}

const response = await generateDqlFromNaturalLanguage(dtClient, text);

let resp = `🔤 Natural Language to DQL:\n\n`;
Expand Down Expand Up @@ -758,6 +767,12 @@ const main = async () => {
dtPlatformToken,
);

// Check if the dql2nl skill is available
const isAvailable = await isDavisCopilotSkillAvailable(dtClient, 'dql2nl');
if (!isAvailable) {
return `❌ The DQL explanation skill is not available. Please visit: ${DAVIS_COPILOT_DOCS.ENABLE_COPILOT}`;
}

const response = await explainDqlInNaturalLanguage(dtClient, dql);

let resp = `📝 DQL to Natural Language:\n\n`;
Expand Down Expand Up @@ -800,6 +815,12 @@ const main = async () => {
dtPlatformToken,
);

// Check if the conversation skill is available
const isAvailable = await isDavisCopilotSkillAvailable(dtClient, 'conversation');
if (!isAvailable) {
return `❌ The conversation skill is not available. Please visit: ${DAVIS_COPILOT_DOCS.ENABLE_COPILOT}`;
}

const conversationContext: any[] = [];

if (context) {
Expand Down