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
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import {
createInternalError,
createToolNotFoundError,
OnechatErrorCode,
createOnechatError,
createAgentNotFoundError,
} from '@kbn/onechat-common';

import { formatOnechatErrorMessage } from './errors';

describe('Onechat errors', () => {
describe('formatOnechatErrorMessage', () => {
it('should format OnechatError instances correctly', () => {
const internalError = createInternalError('Internal server error');
expect(formatOnechatErrorMessage(internalError)).toBe('Internal server error');

const toolNotFoundError = createToolNotFoundError({ toolId: 'missing-tool' });
expect(formatOnechatErrorMessage(toolNotFoundError)).toBe('Tool missing-tool not found');

const agentNotFoundError = createAgentNotFoundError({ agentId: 'missing-agent' });
expect(formatOnechatErrorMessage(agentNotFoundError)).toBe('Agent missing-agent not found');
});

it('should format generic JavaScript errors correctly', () => {
const jsError = new Error('Something went wrong');
expect(formatOnechatErrorMessage(jsError)).toBe('Something went wrong');

const typeError = new TypeError('Invalid type');
expect(formatOnechatErrorMessage(typeError)).toBe('Invalid type');
});

it('should handle string inputs', () => {
expect(formatOnechatErrorMessage('Simple error message')).toBe('Simple error message');
});

it('should handle falsy values', () => {
expect(formatOnechatErrorMessage(null)).toBe('null');
expect(formatOnechatErrorMessage(undefined)).toBe('undefined');
});

it('should handle HTTP response errors with body.message', () => {
const httpError = createOnechatError(OnechatErrorCode.badRequest, 'test error', {
statusCode: 400,
});
expect(formatOnechatErrorMessage(httpError)).toBe('test error');
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { inspect } from 'util';

/*
* Produce a string version of an error,
*/
export function formatOnechatErrorMessage(error: any): string {
if (typeof error === 'string') {
return error;
}

if (!error) {
// stringify undefined/null/whatever this falsy value is
return inspect(error);
}

// handle http response errors with error messages
if (error.body && typeof error.body.message === 'string') {
return error.body.message;
}

// handle standard error objects with messages
if (error instanceof Error && error.message) {
return error.message;
}

// everything else can just be serialized using util.inspect()
return inspect(error);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,4 @@
* 2.0.
*/

export function onechat() {
return 'You know...';
}
export { formatOnechatErrorMessage } from './base/errors';
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,7 @@
"exclude": [
"target/**/*"
],
"kbn_references": []
"kbn_references": [
"@kbn/onechat-common",
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { AgentDefinition } from '@kbn/onechat-common';
import { formatOnechatErrorMessage } from '@kbn/onechat-browser';
import { useForm, Controller, FormProvider } from 'react-hook-form';
import { useAgentEdit } from '../../../hooks/agents/use_agent_edit';
import { useKibana } from '../../../hooks/use_kibana';
Expand Down Expand Up @@ -57,15 +58,17 @@ export const AgentForm: React.FC<AgentFormProps> = ({ agentId }) => {
};

const onSaveError = (err: Error) => {
const errorMessage = isCreateMode
const errorMessageTitle = isCreateMode
? i18n.translate('xpack.onechat.agents.createErrorMessage', {
defaultMessage: 'Failed to create agent',
})
: i18n.translate('xpack.onechat.agents.updateErrorMessage', {
defaultMessage: 'Failed to update agent',
});
notifications.toasts.addError(err, {
title: errorMessage,

notifications.toasts.addDanger({
title: errorMessageTitle,
text: formatOnechatErrorMessage(err),
});
};

Expand All @@ -79,10 +82,11 @@ export const AgentForm: React.FC<AgentFormProps> = ({ agentId }) => {
navigateToOnechatUrl(appPaths.agents.list);
},
onError: (err: Error) => {
notifications.toasts.addError(err, {
notifications.toasts.addDanger({
title: i18n.translate('xpack.onechat.agents.deleteErrorMessage', {
defaultMessage: 'Failed to delete agent',
}),
text: formatOnechatErrorMessage(err),
});
},
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { ToolDefinition } from '@kbn/onechat-common';
import { formatOnechatErrorMessage } from '@kbn/onechat-browser';
import React, { useCallback, useMemo, useState } from 'react';
import { useDeleteToolModal } from '../../../hooks/tools/use_delete_tools';
import { useEsqlTools } from '../../../hooks/tools/use_tools';
Expand Down Expand Up @@ -232,7 +233,7 @@ export const OnechatEsqlTools: React.FC = () => {
title: i18n.translate('xpack.onechat.tools.createEsqlToolErrorToast', {
defaultMessage: 'Unable to create ES|QL tool',
}),
text: error.message,
text: formatOnechatErrorMessage(error),
});
}}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
isToolCallEvent,
isToolResultEvent,
} from '@kbn/onechat-common';
import { formatOnechatErrorMessage } from '@kbn/onechat-browser';
import { createToolCallStep } from '@kbn/onechat-common/chat/conversation';
import { useCallback, useState } from 'react';
import { useConversation } from './use_conversation';
Expand Down Expand Up @@ -92,11 +93,11 @@ export const useChat = ({ connectorId, onError }: UseChatProps = {}) => {
if (isOnechatError(err)) {
onError?.(err);

notifications.toasts.addError(err, {
notifications.toasts.addDanger({
title: i18n.translate('xpack.onechat.chat.chatError.title', {
defaultMessage: 'Error loading chat response',
}),
toastMessage: `${err.code} - ${err.message}`,
text: formatOnechatErrorMessage(err),
});
}
},
Expand Down
1 change: 1 addition & 0 deletions x-pack/platform/plugins/shared/onechat/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"@kbn/config-schema",
"@kbn/inference-plugin",
"@kbn/onechat-server",
"@kbn/onechat-browser",
"@kbn/core-http-server",
"@kbn/onechat-common",
"@kbn/core-elasticsearch-server",
Expand Down