@myrialabs/clopen 0.2.6 → 0.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/backend/chat/stream-manager.ts +24 -13
- package/backend/engine/adapters/claude/stream.ts +10 -19
- package/backend/mcp/project-context.ts +20 -0
- package/backend/mcp/servers/browser-automation/actions.ts +0 -2
- package/backend/mcp/servers/browser-automation/browser.ts +86 -132
- package/backend/mcp/servers/browser-automation/inspection.ts +5 -11
- package/backend/preview/browser/browser-mcp-control.ts +175 -180
- package/backend/preview/browser/browser-pool.ts +3 -1
- package/backend/preview/browser/browser-preview-service.ts +3 -3
- package/backend/preview/browser/browser-tab-manager.ts +1 -1
- package/backend/preview/browser/browser-video-capture.ts +12 -14
- package/backend/preview/browser/scripts/audio-stream.ts +11 -0
- package/backend/preview/browser/scripts/video-stream.ts +14 -14
- package/backend/preview/browser/types.ts +7 -7
- package/backend/preview/index.ts +1 -1
- package/backend/ws/chat/stream.ts +1 -1
- package/backend/ws/preview/browser/tab-info.ts +5 -2
- package/backend/ws/preview/index.ts +3 -3
- package/frontend/components/chat/input/ChatInput.svelte +0 -3
- package/frontend/components/chat/input/composables/use-chat-actions.svelte.ts +6 -2
- package/frontend/components/chat/message/MessageBubble.svelte +2 -2
- package/frontend/components/history/HistoryModal.svelte +1 -1
- package/frontend/components/preview/browser/BrowserPreview.svelte +15 -1
- package/frontend/components/preview/browser/components/Canvas.svelte +323 -49
- package/frontend/components/preview/browser/components/Container.svelte +21 -0
- package/frontend/components/preview/browser/components/Toolbar.svelte +3 -3
- package/frontend/components/preview/browser/core/coordinator.svelte.ts +15 -0
- package/frontend/components/preview/browser/core/mcp-handlers.svelte.ts +78 -51
- package/frontend/components/preview/browser/core/tab-operations.svelte.ts +1 -0
- package/frontend/components/workspace/PanelHeader.svelte +15 -0
- package/frontend/components/workspace/panels/GitPanel.svelte +22 -13
- package/frontend/components/workspace/panels/PreviewPanel.svelte +2 -0
- package/frontend/services/chat/chat.service.ts +3 -7
- package/frontend/services/preview/browser/browser-webcodecs.service.ts +32 -135
- package/frontend/stores/core/app.svelte.ts +4 -3
- package/frontend/stores/core/presence.svelte.ts +3 -2
- package/frontend/stores/core/sessions.svelte.ts +2 -0
- package/frontend/stores/ui/notification.svelte.ts +4 -1
- package/package.json +1 -1
|
@@ -470,7 +470,7 @@ export const streamHandler = createRouter()
|
|
|
470
470
|
return;
|
|
471
471
|
}
|
|
472
472
|
|
|
473
|
-
|
|
473
|
+
await streamManager.cancelStream(streamState.streamId);
|
|
474
474
|
// Always send cancelled to chat session room to clear UI
|
|
475
475
|
ws.emit.chatSession(chatSessionId, 'chat:cancelled', {
|
|
476
476
|
status: 'cancelled',
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import { t } from 'elysia';
|
|
8
8
|
import { createRouter } from '$shared/utils/ws-server';
|
|
9
9
|
import { browserPreviewServiceManager } from '../../../preview/index';
|
|
10
|
+
import { browserMcpControl } from '../../../preview/browser/browser-mcp-control';
|
|
10
11
|
import { ws } from '$backend/utils/ws';
|
|
11
12
|
import { debug } from '$shared/utils/logger';
|
|
12
13
|
|
|
@@ -62,7 +63,8 @@ export const tabInfoPreviewHandler = createRouter()
|
|
|
62
63
|
isStreaming: t.Boolean(),
|
|
63
64
|
deviceSize: t.String(),
|
|
64
65
|
rotation: t.String(),
|
|
65
|
-
isActive: t.Boolean()
|
|
66
|
+
isActive: t.Boolean(),
|
|
67
|
+
isMcpControlled: t.Boolean()
|
|
66
68
|
})),
|
|
67
69
|
activeTabId: t.Union([t.String(), t.Null()]),
|
|
68
70
|
count: t.Number()
|
|
@@ -87,7 +89,8 @@ export const tabInfoPreviewHandler = createRouter()
|
|
|
87
89
|
isStreaming: tab.isStreaming,
|
|
88
90
|
deviceSize: tab.deviceSize,
|
|
89
91
|
rotation: tab.rotation,
|
|
90
|
-
isActive: tab.isActive
|
|
92
|
+
isActive: tab.isActive,
|
|
93
|
+
isMcpControlled: browserMcpControl.isTabControlled(tab.id, projectId)
|
|
91
94
|
})),
|
|
92
95
|
activeTabId: activeTab?.id || null,
|
|
93
96
|
count: allTabsInfo.length
|
|
@@ -117,12 +117,12 @@ export const previewRouter = createRouter()
|
|
|
117
117
|
}))
|
|
118
118
|
// MCP control events
|
|
119
119
|
.emit('preview:browser-mcp-control-start', t.Object({
|
|
120
|
-
|
|
121
|
-
|
|
120
|
+
browserTabId: t.String(),
|
|
121
|
+
chatSessionId: t.Optional(t.String()),
|
|
122
122
|
timestamp: t.Number()
|
|
123
123
|
}))
|
|
124
124
|
.emit('preview:browser-mcp-control-end', t.Object({
|
|
125
|
-
|
|
125
|
+
browserTabId: t.String(),
|
|
126
126
|
timestamp: t.Number()
|
|
127
127
|
}))
|
|
128
128
|
.emit('preview:browser-mcp-cursor-position', t.Object({
|
|
@@ -10,7 +10,6 @@ import { debug } from '$shared/utils/logger';
|
|
|
10
10
|
import type { FileAttachment } from './use-file-handling.svelte';
|
|
11
11
|
|
|
12
12
|
interface ChatActionsParams {
|
|
13
|
-
messageText: string;
|
|
14
13
|
attachedFiles: FileAttachment[];
|
|
15
14
|
clearAllAttachments: () => void;
|
|
16
15
|
adjustTextareaHeight: () => void;
|
|
@@ -27,7 +26,6 @@ export function useChatActions(params: ChatActionsParams) {
|
|
|
27
26
|
function handleCancelEdit() {
|
|
28
27
|
cancelEdit();
|
|
29
28
|
clearInput();
|
|
30
|
-
params.messageText = ''; // This won't work directly, need to pass setter
|
|
31
29
|
params.clearAllAttachments();
|
|
32
30
|
params.adjustTextareaHeight();
|
|
33
31
|
}
|
|
@@ -52,6 +50,12 @@ export function useChatActions(params: ChatActionsParams) {
|
|
|
52
50
|
await snapshotService.restore(restoreTargetId, sessionState.currentSession.id);
|
|
53
51
|
}
|
|
54
52
|
|
|
53
|
+
// Set skip and clear draft BEFORE reloading messages — editing the first message
|
|
54
|
+
// causes messages to become empty (welcome state), which remounts ChatInput.
|
|
55
|
+
// Without this, the new instance restores stale server state into the input.
|
|
56
|
+
setSkipNextRestore(true);
|
|
57
|
+
params.clearDraft();
|
|
58
|
+
|
|
55
59
|
// Reload messages from database to update UI
|
|
56
60
|
if (sessionState.currentSession?.id) {
|
|
57
61
|
await loadMessagesForSession(sessionState.currentSession.id);
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
|
|
53
53
|
// Auto-scroll reasoning/system content to bottom while receiving partial text
|
|
54
54
|
$effect(() => {
|
|
55
|
-
if (roleCategory !== 'reasoning' && roleCategory !== 'system') return;
|
|
55
|
+
if (roleCategory !== 'reasoning' && roleCategory !== 'system' && roleCategory !== 'compact') return;
|
|
56
56
|
if (!scrollContainer) return;
|
|
57
57
|
// Track message content changes (partialText for streaming, message for final)
|
|
58
58
|
const _track = message.type === 'stream_event' && 'partialText' in message
|
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
<!-- Message Content -->
|
|
94
94
|
<div
|
|
95
95
|
bind:this={scrollContainer}
|
|
96
|
-
class="p-3 md:p-4 {roleCategory === 'reasoning' || roleCategory === 'system' ? 'max-h-80 overflow-y-auto' : ''}"
|
|
96
|
+
class="p-3 md:p-4 {roleCategory === 'reasoning' || roleCategory === 'system' || roleCategory === 'compact' ? 'max-h-80 overflow-y-auto' : ''}"
|
|
97
97
|
>
|
|
98
98
|
<div class="max-w-none space-y-4">
|
|
99
99
|
<!-- Content rendering using MessageFormatter component -->
|
|
@@ -428,7 +428,7 @@
|
|
|
428
428
|
<span
|
|
429
429
|
class="absolute -bottom-0.5 -right-0.5 w-2.5 h-2.5 rounded-full border-2 border-white dark:border-slate-900 {isSessionWaitingInput(session.id, projectState.currentProject?.id) ? 'bg-amber-500' : 'bg-emerald-500'}"
|
|
430
430
|
></span>
|
|
431
|
-
{:else if isSessionUnread(session.id)}
|
|
431
|
+
{:else if isSessionUnread(session.id) && session.id !== sessionState.currentSession?.id}
|
|
432
432
|
<span
|
|
433
433
|
class="absolute -bottom-0.5 -right-0.5 w-2.5 h-2.5 rounded-full border-2 border-white dark:border-slate-900 bg-blue-500"
|
|
434
434
|
></span>
|
|
@@ -61,6 +61,9 @@
|
|
|
61
61
|
// Flag to prevent URL watcher from double-launching during MCP session creation
|
|
62
62
|
const mcpLaunchInProgress = $state(false);
|
|
63
63
|
|
|
64
|
+
// Touch interaction mode for canvas
|
|
65
|
+
let touchMode = $state<'scroll' | 'cursor'>('scroll');
|
|
66
|
+
|
|
64
67
|
// Flag to track if sessions were recovered (prevents creating empty tab on mount)
|
|
65
68
|
let sessionsRecovered = $state(false);
|
|
66
69
|
|
|
@@ -417,6 +420,14 @@
|
|
|
417
420
|
return mcpHandler.isCurrentTabMcpControlled();
|
|
418
421
|
}
|
|
419
422
|
|
|
423
|
+
// Hide MCP virtual cursor when switching to a non-MCP-controlled tab
|
|
424
|
+
$effect(() => {
|
|
425
|
+
void activeTabId; // track activeTabId changes
|
|
426
|
+
if (!isCurrentTabMcpControlled()) {
|
|
427
|
+
mcpVirtualCursor = { x: 0, y: 0, visible: false, clicking: false };
|
|
428
|
+
}
|
|
429
|
+
});
|
|
430
|
+
|
|
420
431
|
// Stream message handling
|
|
421
432
|
$effect(() => {
|
|
422
433
|
if (activeTabId && sessionId) {
|
|
@@ -426,6 +437,8 @@
|
|
|
426
437
|
|
|
427
438
|
// Expose methods for parent (PreviewPanel)
|
|
428
439
|
export const browserActions = {
|
|
440
|
+
getTouchMode: () => touchMode,
|
|
441
|
+
setTouchMode: (mode: 'scroll' | 'cursor') => { touchMode = mode; },
|
|
429
442
|
changeDeviceSize: (size: DeviceSize) => {
|
|
430
443
|
coordinator.changeDeviceSize(size, previewDimensions?.scale);
|
|
431
444
|
},
|
|
@@ -460,7 +473,7 @@
|
|
|
460
473
|
bind:isConsoleOpen
|
|
461
474
|
{tabs}
|
|
462
475
|
{activeTabId}
|
|
463
|
-
|
|
476
|
+
mcpControlledTabIds={mcpHandler.getControlledTabIds()}
|
|
464
477
|
onGoClick={handleGoClick}
|
|
465
478
|
onRefresh={refreshPreview}
|
|
466
479
|
onOpenInExternalBrowser={() => {}}
|
|
@@ -494,6 +507,7 @@
|
|
|
494
507
|
bind:canvasAPI
|
|
495
508
|
bind:previewDimensions
|
|
496
509
|
bind:lastFrameData={currentTabLastFrameData}
|
|
510
|
+
bind:touchMode
|
|
497
511
|
isMcpControlled={isCurrentTabMcpControlled()}
|
|
498
512
|
onInteraction={handleCanvasInteraction}
|
|
499
513
|
onRetry={handleGoClick}
|