Skip to content

Commit e4d9786

Browse files
committed
Test livemate shell execution
1 parent 9be44dc commit e4d9786

4 files changed

Lines changed: 136 additions & 47 deletions

File tree

front_end/core/host/InspectorFrontendHost.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,9 @@ export class InspectorFrontendHostStub implements InspectorFrontendHostAPI {
141141
bringToFront(): void {
142142
}
143143

144+
sendToDevmate(prompt: string): void {
145+
}
146+
144147
closeWindow(): void {
145148
}
146149

front_end/core/host/InspectorFrontendHostAPI.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,8 @@ export interface InspectorFrontendHostAPI {
297297

298298
bringToFront(): void;
299299

300+
sendToDevmate(prompt: string): void;
301+
300302
closeWindow(): void;
301303

302304
copyText(text: string|null|undefined): void;
@@ -453,6 +455,12 @@ export interface SyncInformation {
453455
isSyncPaused?: boolean;
454456
}
455457

458+
export interface FileWriteResult {
459+
success: boolean;
460+
path: string|null;
461+
error?: string;
462+
}
463+
456464
/**
457465
* Enum for recordPerformanceHistogram
458466
* Warning: There is another definition of this enum in the DevTools code
Lines changed: 48 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1-
// Copyright (c) Meta Platforms, Inc. and affiliates.
2-
// Copyright 2024 The Chromium Authors. All rights reserved.
1+
// Copyright 2025 The Chromium Authors. All rights reserved.
32
// Use of this source code is governed by a BSD-style license that can be
43
// found in the LICENSE file.
54

6-
import * as UI from '../../ui/legacy/legacy.js';
7-
import livematePanelStyles from './livematePanel.css.js';
8-
import * as SDK from '../../core/sdk/sdk.js';
9-
import { ReactDevToolsViewBase } from '../react_devtools/ReactDevToolsViewBase.js';
5+
import * as Host from '../../core/host/host.js';
106
import * as i18n from '../../core/i18n/i18n.js';
7+
import { ReactDevToolsViewBase } from '../react_devtools/ReactDevToolsViewBase.js';
8+
9+
import livematePanelStyles from './livematePanel.css.js';
1110

1211
let livematePanelInstance: LivematePanel;
1312

@@ -17,7 +16,10 @@ const UIStrings = {
1716
*/
1817
title: '⚛️ Livemate',
1918
} as const;
20-
const str_ = i18n.i18n.registerUIStrings('panels/livemate/LivematePanel.ts', UIStrings);
19+
const str_ = i18n.i18n.registerUIStrings(
20+
'panels/livemate/LivematePanel.ts',
21+
UIStrings
22+
);
2123
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
2224

2325
export class LivematePanel extends ReactDevToolsViewBase {
@@ -28,48 +30,56 @@ export class LivematePanel extends ReactDevToolsViewBase {
2830
return livematePanelInstance;
2931
}
3032

31-
constructor() {
33+
constructor() {
3234
super('components', i18nString(UIStrings.title));
35+
this.registerRequiredCSS(livematePanelStyles);
3336
}
3437

3538
override renderDevToolsView(): void {
3639
this.clearView();
3740

38-
const model = this.model;
39-
if (model === null) {
40-
throw new Error('Attempted to render React DevTools panel, but the model was null');
41-
}
41+
this.contentElement.classList.add('livemate-panel');
4242

43-
const bridge = model.getBridgeOrThrow();
43+
const promptSection = this.contentElement.createChild(
44+
'div',
45+
'livemate-prompt-section'
46+
);
4447

45-
const button = document.createElement('button');
46-
button.textContent = 'Start Inspecting Host';
48+
const promptTextarea = document.createElement('textarea');
49+
promptTextarea.className = 'livemate-prompt-input';
50+
promptTextarea.placeholder = 'Ask Devmate anything about this app...';
51+
promptSection.appendChild(promptTextarea);
4752

48-
bridge.addListener('selectElement', (element: any) => {console.log(element)});
53+
const sendButton = promptSection.createChild(
54+
'button',
55+
'livemate-send-button'
56+
);
57+
sendButton.textContent = 'Send to Devmate';
4958

50-
let inspecting = false;
59+
const statusArea = promptSection.createChild('div', 'livemate-status');
5160

52-
button.onclick = () => {
53-
if (inspecting) {
54-
(bridge as any).send('stopInspectingHost');
55-
button.textContent= 'Start Inspecting Host';
56-
inspecting = false;
57-
} else {
58-
(bridge as any).send('startInspectingHost', false);
59-
button.textContent= 'Stop Inspecting Host';
60-
inspecting = true;
61+
const handleSend = (): void => {
62+
const prompt = promptTextarea.value.trim();
63+
if (!prompt) {
64+
statusArea.textContent = 'Please enter a prompt';
65+
statusArea.className = 'livemate-status error';
66+
return;
6167
}
62-
}
63-
64-
this.contentElement.appendChild(button);
65-
66-
67-
68-
// bridge.send('stopInspectingHost');
68+
statusArea.textContent = 'Sending to Devmate...';
69+
statusArea.className = 'livemate-status pending';
70+
71+
(
72+
Host.InspectorFrontendHost.InspectorFrontendHostInstance as unknown as {
73+
sendToDevmate: (prompt: string) => void,
74+
}
75+
).sendToDevmate(prompt);
76+
};
77+
78+
sendButton.addEventListener('click', handleSend);
79+
promptTextarea.addEventListener('keydown', e => {
80+
if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) {
81+
handleSend();
82+
}
83+
});
6984
}
70-
71-
// this.contentElement.removeChildren();
72-
73-
// const header = this.contentElement.createChild('div', 'livemate-header');
74-
// header.textContent = 'Livemate Panel';
7585
}
Lines changed: 77 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,88 @@
11
.livemate-panel {
22
display: flex;
33
flex-direction: column;
4-
overflow: auto;
5-
padding: 12px;
4+
height: 100%;
5+
padding: 16px;
66
background-color: var(--sys-color-cdt-base-container);
7+
box-sizing: border-box;
78
}
89

9-
.livemate-header {
10-
font-size: 18px;
11-
font-weight: 500;
12-
margin-bottom: 16px;
13-
color: var(--sys-color-on-surface);
10+
.livemate-prompt-section {
11+
display: flex;
12+
flex-direction: column;
13+
gap: 12px;
14+
max-width: 600px;
15+
width: 100%;
16+
margin: 0 auto;
1417
}
1518

16-
.livemate-content {
19+
.livemate-prompt-input {
20+
width: 100%;
21+
min-height: 120px;
22+
padding: 12px;
23+
border: 1px solid var(--sys-color-divider);
24+
border-radius: 8px;
25+
font-family: inherit;
1726
font-size: 14px;
27+
line-height: 1.5;
28+
resize: vertical;
29+
background-color: var(--sys-color-surface);
1830
color: var(--sys-color-on-surface);
19-
line-height: 1.6;
31+
box-sizing: border-box;
32+
}
33+
34+
.livemate-prompt-input::placeholder {
35+
color: var(--sys-color-state-disabled-container);
36+
}
37+
38+
.livemate-prompt-input:focus {
39+
outline: none;
40+
border-color: var(--sys-color-primary);
41+
box-shadow: 0 0 0 1px var(--sys-color-primary);
42+
}
43+
44+
.livemate-send-button {
45+
align-self: flex-start;
46+
padding: 8px 16px;
47+
font-size: 13px;
48+
font-weight: 500;
49+
border-radius: 4px;
50+
border: none;
51+
background-color: var(--sys-color-primary);
52+
color: var(--sys-color-on-primary);
53+
cursor: pointer;
54+
transition: background-color 0.15s ease;
55+
}
56+
57+
.livemate-send-button:hover {
58+
background-color: var(--sys-color-primary-hover);
59+
}
60+
61+
.livemate-send-button:active {
62+
background-color: var(--sys-color-primary-pressed);
63+
}
64+
65+
.livemate-status {
66+
padding: 8px 12px;
67+
border-radius: 4px;
68+
font-size: 13px;
69+
}
70+
71+
.livemate-status:empty {
72+
display: none;
73+
}
74+
75+
.livemate-status.error {
76+
background-color: var(--sys-color-error-container);
77+
color: var(--sys-color-error);
78+
}
79+
80+
.livemate-status.success {
81+
background-color: var(--sys-color-green-container);
82+
color: var(--sys-color-green);
83+
}
84+
85+
.livemate-status.pending {
86+
background-color: var(--sys-color-tonal-container);
87+
color: var(--sys-color-primary);
2088
}

0 commit comments

Comments
 (0)