mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-30 23:14:37 +00:00
* feat(webhooks): refactor webhook URL handling and enhance API endpoints - Introduced a new utility function `buildWebhookIngressUrl` to standardize the construction of webhook URLs across components. - Updated `WebhooksDebugPanel` and `TunnelList` components to utilize the new URL builder for improved consistency and maintainability. - Refactored API endpoints in `tunnelsApi` to reflect changes in webhook routing, ensuring all references to tunnel management are aligned with the new structure. - Adjusted user API calls to replace `/telegram/me` with `/auth/me` for better clarity and consistency in authentication flows. - Enhanced socket service to normalize channel connection update payloads, improving error handling and data integrity. These changes streamline webhook management and enhance the overall developer experience when working with webhooks. * feat(messaging): enhance Telegram and Discord channel linking functionality - Added support for managed DM linking with Telegram and OAuth flow for Discord. - Introduced `createChannelLinkToken` API to generate short-lived link tokens for messaging channels. - Updated `MessagingPanel` to handle managed linking flows, including building launch URLs and user instructions. - Enhanced configuration to include a Telegram bot username for fallback linking. - Updated tests to mock new configuration values for consistent testing. These changes improve the user experience for linking messaging channels and streamline the authentication process. * feat(api): introduce core command client and refactor API calls - Added a new `coreCommandClient` to facilitate RPC calls to core services. - Refactored existing API endpoints in `authApi`, `billingApi`, `creditsApi`, `tunnelsApi`, and `userApi` to utilize the new command client for improved consistency and maintainability. - Updated the billing API to include new endpoints for fetching balance, transactions, and managing auto-recharge settings. - Enhanced the user API to streamline user data retrieval. - Improved error handling and logging across the refactored API calls. These changes enhance the overall architecture of the API services, making them more modular and easier to maintain. * refactor(api): streamline API calls and enhance error handling - Refactored `creditsApi` and `tunnelsApi` to ensure consistent use of the new core command client. - Updated API methods to improve error handling and response parsing. - Introduced a new `authed_json` method in `BackendOAuthClient` for standardized authenticated requests. - Cleaned up unused imports and optimized code structure across various modules. These changes enhance the maintainability and reliability of the API services. * refactor(api): streamline API calls and improve code readability - Reorganized API calls in `authApi`, `billingApi`, `creditsApi`, and `tunnelsApi` to enhance consistency and maintainability. - Updated function formatting for better readability, ensuring parameters are clearly defined. - Cleaned up import statements and removed unnecessary line breaks to improve code clarity. These changes contribute to a more maintainable codebase and enhance the overall developer experience. * refactor(MessagingPanel): clean up imports and remove unused constants - Reorganized import statements for clarity and consistency. - Removed unused constants related to channel definitions and status styles to streamline the component. - Simplified the `updateField` function call in the rendering logic for better readability. These changes enhance the maintainability of the MessagingPanel component. * fix: restore helper functions removed during merge cleanup buildManagedChannelLaunchUrl and buildManagedChannelInstruction were stripped by the linter after merge resolution, breaking the build. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(messaging): enhance MessagingPanel with pending instruction handling - Introduced a new state for pending instructions to improve user feedback during channel connection processes. - Updated error handling to ensure users receive clear instructions, including URLs for manual access if automatic opening fails. - Refactored connection status updates to streamline the dispatch process and improve code readability. - Enhanced the rendering logic to display pending instructions in the UI, providing better context for users during authentication flows. * fix(api): encode channel and ID parameters in webhook and OAuth URLs - Updated the URL construction in the BackendOAuthClient to encode the channel parameter, ensuring proper formatting for requests. - Modified the get_tunnel, update_tunnel, and delete_tunnel functions to encode the ID parameter in webhook URLs, enhancing security and compatibility with special characters. * fix(auth): validate channel input for link token creation - Added validation to ensure the channel is not empty and is one of the supported types (telegram, discord). - Converted the channel string to lowercase for consistent matching. - Updated the call to create_channel_link_token to use a reference to the channel variable. * chore(todos): update TODO list with completed tasks and new feature requests - Marked several tasks as completed, including integration of the custom memory engine and skills registry into the core. - Added new items to the TODO list, including improvements for voiceover functionalities, screen intelligence, and Gmail skill enhancements. - Included tasks for debugging skills from the UI and improving prompts to reduce hallucinations. * refactor(webhooks): improve formatting of get_tunnel function for readability - Reformatted the get_tunnel function to enhance code clarity by adjusting the indentation and line breaks in the call to get_authed_value. - This change improves the maintainability of the code and aligns with the overall code style. * test(userApi): enhance userApi tests with improved mocking and error handling - Added a mock function for core command calls to streamline test setup. - Introduced a helper function to generate mock user data for consistent test cases. - Updated tests to use the mock function for simulating API responses, improving clarity and maintainability. - Enhanced error handling in tests to cover various API error scenarios, ensuring robustness in userApi.getMe functionality. * refactor(billingApi): update tests to use core command mocking and improve error handling - Replaced apiClient mocks with core command mocks for better alignment with the new API structure. - Updated test cases to reflect changes in API call expectations, enhancing clarity and maintainability. - Improved error handling in tests to ensure proper propagation of errors from core command calls. * refactor(billingApi): simplify test cases by consolidating mock function calls - Streamlined mock function calls in billingApi tests for improved readability and consistency. - Removed unnecessary line breaks in mock responses, enhancing clarity in test definitions. - Ensured that error handling and API call expectations are clearly represented in the tests. * refactor(api): rename settings endpoint to current_user for clarity - Updated the endpoint handling authenticated profile fetches to improve clarity in the codebase. - Adjusted the routing to reflect the new function name, enhancing maintainability and understanding of the API's purpose. --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
167 lines
6.0 KiB
TypeScript
167 lines
6.0 KiB
TypeScript
// @ts-nocheck
|
|
import { waitForApp, waitForAppReady } from '../helpers/app-helpers';
|
|
import { triggerAuthDeepLinkBypass } from '../helpers/deep-link-helpers';
|
|
import {
|
|
clickText,
|
|
dumpAccessibilityTree,
|
|
textExists,
|
|
waitForText,
|
|
waitForWebView,
|
|
waitForWindowVisible,
|
|
} from '../helpers/element-helpers';
|
|
import {
|
|
completeOnboardingIfVisible,
|
|
navigateToConversations,
|
|
navigateViaHash,
|
|
} from '../helpers/shared-flows';
|
|
import { clearRequestLog, getRequestLog, startMockServer, stopMockServer } from '../mock-server';
|
|
|
|
function stepLog(message: string, context?: unknown) {
|
|
const stamp = new Date().toISOString();
|
|
if (context === undefined) {
|
|
console.log(`[ConversationsE2E][${stamp}] ${message}`);
|
|
return;
|
|
}
|
|
console.log(`[ConversationsE2E][${stamp}] ${message}`, JSON.stringify(context, null, 2));
|
|
}
|
|
|
|
async function waitForRequest(method, urlFragment, timeout = 20_000) {
|
|
const deadline = Date.now() + timeout;
|
|
while (Date.now() < deadline) {
|
|
const log = getRequestLog();
|
|
const match = log.find(r => r.method === method && r.url.includes(urlFragment));
|
|
if (match) return match;
|
|
await browser.pause(500);
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
// This spec tests the full agent chat loop (UI → core sidecar → backend → streaming response).
|
|
// On Linux CI, the core sidecar's chat pipeline may not be fully functional in the E2E
|
|
// environment (mock backend lacks streaming SSE support). Skip on Linux only.
|
|
const suiteRunner = process.platform === 'linux' ? describe.skip : describe;
|
|
suiteRunner('Conversations web channel flow', () => {
|
|
before(async () => {
|
|
stepLog('starting mock server');
|
|
await startMockServer();
|
|
stepLog('waiting for app');
|
|
await waitForApp();
|
|
stepLog('clearing request log');
|
|
clearRequestLog();
|
|
});
|
|
|
|
after(async () => {
|
|
stepLog('stopping mock server');
|
|
await stopMockServer();
|
|
});
|
|
|
|
it('sends UI message through agent loop and renders response', async () => {
|
|
stepLog('trigger deep link');
|
|
await triggerAuthDeepLinkBypass('e2e-conversations-token');
|
|
stepLog('wait for window');
|
|
await waitForWindowVisible(25_000);
|
|
stepLog('wait for webview');
|
|
await waitForWebView(15_000);
|
|
stepLog('wait for app ready');
|
|
await waitForAppReady(15_000);
|
|
|
|
// triggerAuthDeepLinkBypass uses key=auth which sets the token directly
|
|
// (no /telegram/login-tokens/ consume call). Wait for user profile instead.
|
|
stepLog('wait for user profile request');
|
|
const profileCall = await waitForRequest('GET', '/auth/me', 15_000);
|
|
if (!profileCall) {
|
|
stepLog('user profile call not found — bypass token may have been set without API call');
|
|
}
|
|
|
|
stepLog('complete onboarding');
|
|
await completeOnboardingIfVisible('[ConversationsE2E]');
|
|
|
|
stepLog('open conversations');
|
|
// Navigate via hash — "Message OpenHuman" button may not reliably open conversations
|
|
await navigateToConversations();
|
|
// If navigating to /conversations doesn't open a thread, try clicking the input area
|
|
const hasInput = await textExists('Type a message...');
|
|
if (!hasInput) {
|
|
// Try the home page "Message OpenHuman" button as fallback
|
|
await navigateViaHash('/home');
|
|
try {
|
|
await waitForText('Message OpenHuman', 10_000);
|
|
await clickText('Message OpenHuman', 10_000);
|
|
} catch {
|
|
stepLog('Message OpenHuman button not found, staying on conversations');
|
|
await navigateToConversations();
|
|
}
|
|
}
|
|
|
|
stepLog('send message');
|
|
// The chat input uses a textarea with placeholder attribute — not visible as text content.
|
|
// Use browser.execute to find and focus it, then type.
|
|
const foundInput = await browser.execute(() => {
|
|
const textarea = document.querySelector(
|
|
'textarea[placeholder*="Type a message"]'
|
|
) as HTMLTextAreaElement;
|
|
if (textarea) {
|
|
textarea.focus();
|
|
textarea.click();
|
|
return true;
|
|
}
|
|
// Fallback: any textarea or contenteditable
|
|
const fallback = document.querySelector('textarea, [contenteditable="true"]') as HTMLElement;
|
|
if (fallback) {
|
|
fallback.focus();
|
|
(fallback as HTMLElement).click();
|
|
return true;
|
|
}
|
|
return false;
|
|
});
|
|
if (!foundInput) {
|
|
const tree = await dumpAccessibilityTree();
|
|
stepLog('Chat input not found. Tree:', tree.slice(0, 4000));
|
|
throw new Error('Chat input textarea not found');
|
|
}
|
|
stepLog('Chat input focused');
|
|
await browser.pause(500);
|
|
|
|
// Set value via JS and dispatch input event (browser.keys unreliable on tauri-driver)
|
|
await browser.execute(() => {
|
|
const textarea = document.querySelector(
|
|
'textarea[placeholder*="Type a message"]'
|
|
) as HTMLTextAreaElement;
|
|
if (!textarea) return;
|
|
const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
|
|
window.HTMLTextAreaElement.prototype,
|
|
'value'
|
|
)?.set;
|
|
nativeInputValueSetter?.call(textarea, 'hello from e2e web channel');
|
|
textarea.dispatchEvent(new Event('input', { bubbles: true }));
|
|
textarea.dispatchEvent(new Event('change', { bubbles: true }));
|
|
});
|
|
await browser.pause(500);
|
|
|
|
// Submit by pressing Enter via JS (simulates form submission)
|
|
await browser.execute(() => {
|
|
const textarea = document.querySelector(
|
|
'textarea[placeholder*="Type a message"]'
|
|
) as HTMLTextAreaElement;
|
|
if (!textarea) return;
|
|
textarea.dispatchEvent(
|
|
new KeyboardEvent('keydown', { key: 'Enter', code: 'Enter', bubbles: true })
|
|
);
|
|
});
|
|
await browser.pause(1_000);
|
|
|
|
await waitForText('hello from e2e web channel', 20_000);
|
|
await waitForText('Hello from e2e mock agent', 30_000);
|
|
|
|
stepLog('validate backend request');
|
|
const chatReq = await waitForRequest('POST', '/openai/v1/chat/completions', 30_000);
|
|
if (!chatReq) {
|
|
const tree = await dumpAccessibilityTree();
|
|
console.log('[ConversationsE2E] Missing openai chat request. Tree:\n', tree.slice(0, 5000));
|
|
}
|
|
expect(chatReq).toBeDefined();
|
|
|
|
expect(await textExists('chat_send is not available')).toBe(false);
|
|
});
|
|
});
|