Skip to content

Commit 2931e91

Browse files
authored
fix: add active branch context when page selected (#2911)
1 parent b616f66 commit 2931e91

File tree

8 files changed

+60
-40
lines changed

8 files changed

+60
-40
lines changed

apps/web/client/src/app/api/chat/route.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ export const streamResponse = async (req: NextRequest, userId: string) => {
8181
const { model, providerOptions, headers } = modelConfig;
8282
const systemPrompt = getSystemPromptFromType(chatType);
8383
const tools = getToolSetFromType(chatType);
84-
8584
const result = streamText({
8685
model,
8786
headers,

apps/web/client/src/components/store/editor/chat/context.ts

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
import { assertNever, type ParsedError } from '@onlook/utility';
1313
import { makeAutoObservable, reaction } from 'mobx';
1414
import type { EditorEngine } from '../engine';
15+
import type { FrameData } from '../frames';
1516

1617
export class ChatContext {
1718
private _context: MessageContext[] = [];
@@ -23,8 +24,13 @@ export class ChatContext {
2324

2425
init() {
2526
this.selectedReactionDisposer = reaction(
26-
() => this.editorEngine.elements.selected,
27-
() => this.generateContextFromReaction().then((context) => (this.context = context)),
27+
() => ({
28+
elements: this.editorEngine.elements.selected,
29+
frames: this.editorEngine.frames.selected,
30+
}),
31+
(
32+
{ elements, frames },
33+
) => this.generateContextFromReaction({ elements, frames }).then((context) => (this.context = context)),
2834
);
2935
}
3036

@@ -57,18 +63,16 @@ export class ChatContext {
5763
return await this.getRefreshedContext(this.context);
5864
}
5965

60-
private async generateContextFromReaction(): Promise<MessageContext[]> {
61-
const selected = this.editorEngine.elements.selected;
62-
66+
private async generateContextFromReaction({ elements, frames }: { elements: DomElement[], frames: FrameData[] }): Promise<MessageContext[]> {
6367
let highlightedContext: HighlightMessageContext[] = [];
64-
if (selected.length) {
65-
highlightedContext = await this.getHighlightedContext(selected);
68+
if (elements.length) {
69+
highlightedContext = await this.getHighlightedContext(elements);
6670
}
6771
const imageContext = await this.getImageContext();
6872

6973
// Derived from highlighted context
7074
const fileContext = await this.getFileContext(highlightedContext);
71-
const branchContext = this.getBranchContext(highlightedContext);
75+
const branchContext = this.getBranchContext(highlightedContext, frames);
7276
const context = [...fileContext, ...highlightedContext, ...imageContext, ...branchContext];
7377
return context;
7478
}
@@ -132,9 +136,13 @@ export class ChatContext {
132136
return fileContext;
133137
}
134138

135-
getBranchContext(highlightedContext: HighlightMessageContext[]): BranchMessageContext[] {
136-
// Get unique branch IDs from highlighted context
137-
const uniqueBranchIds = new Set<string>();
139+
getBranchContext(
140+
highlightedContext: HighlightMessageContext[],
141+
frames: FrameData[],
142+
): BranchMessageContext[] {
143+
// Get unique branch IDs from selected elements and frames context
144+
const uniqueBranchIds = new Set<string>(frames.map(frame => frame.frame.branchId));
145+
138146
highlightedContext.forEach(highlight => {
139147
uniqueBranchIds.add(highlight.branchId);
140148
});

packages/ai/src/prompt/provider.ts

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
import type {
2-
ChatMessage,
3-
ErrorMessageContext,
4-
FileMessageContext,
5-
HighlightMessageContext,
6-
MessageContext,
7-
ProjectMessageContext,
1+
import {
2+
MessageContextType,
3+
type BranchMessageContext,
4+
type ChatMessage,
5+
type ErrorMessageContext,
6+
type FileMessageContext,
7+
type HighlightMessageContext,
8+
type MessageContext,
9+
type ProjectMessageContext,
810
} from '@onlook/models';
911
import type { FileUIPart } from 'ai';
1012
import { ASK_MODE_SYSTEM_PROMPT, CODE_FENCE, CONTEXT_PROMPTS, CREATE_NEW_PAGE_SYSTEM_PROMPT, SHELL_PROMPT, SUGGESTION_SYSTEM_PROMPT, SUMMARY_PROMPTS, SYSTEM_PROMPT } from './constants';
@@ -62,11 +64,12 @@ export function getHydratedUserMessage(
6264
opt: HydrateMessageOptions,
6365
): ChatMessage {
6466
let userParts: ChatMessage['parts'] = [];
65-
const files = context.filter((c) => c.type === 'file').map((c) => c);
66-
const highlights = context.filter((c) => c.type === 'highlight').map((c) => c);
67-
const errors = context.filter((c) => c.type === 'error').map((c) => c);
68-
const project = context.filter((c) => c.type === 'project').map((c) => c);
69-
const images = context.filter((c) => c.type === 'image').map((c) => c);
67+
const files = context.filter((c) => c.type === MessageContextType.FILE).map((c) => c);
68+
const highlights = context.filter((c) => c.type === MessageContextType.HIGHLIGHT).map((c) => c);
69+
const errors = context.filter((c) => c.type === MessageContextType.ERROR).map((c) => c);
70+
const project = context.filter((c) => c.type === MessageContextType.PROJECT).map((c) => c);
71+
const images = context.filter((c) => c.type === MessageContextType.IMAGE).map((c) => c);
72+
const branches = context.filter((c) => c.type === MessageContextType.BRANCH).map((c) => c);
7073

7174
// If there are 50 user messages in the contexts, we can trim all of them except
7275
// the last one. The logic could be adjusted to trim more or less messages.
@@ -87,7 +90,7 @@ export function getHydratedUserMessage(
8790
}
8891

8992
if (errors.length > 0) {
90-
let errorPrompt = getErrorsContent(errors);
93+
const errorPrompt = getErrorsContent(errors);
9194
prompt += errorPrompt;
9295
}
9396

@@ -98,6 +101,11 @@ export function getHydratedUserMessage(
98101
}
99102
}
100103

104+
if (branches.length > 0) {
105+
const branchPrompt = getBranchesContent(branches);
106+
prompt += branchPrompt;
107+
}
108+
101109
const textContent = parts
102110
.filter((p) => p.type === 'text')
103111
.map((p) => p.text)
@@ -130,7 +138,7 @@ export function getTruncatedFilesContent(files: FileMessageContext[]) {
130138
prompt += `${CONTEXT_PROMPTS.truncatedFilesContentPrefix}\n`;
131139
let index = 1;
132140
for (const file of files) {
133-
const branchDisplay = getBranchesContent(file.branchId);
141+
const branchDisplay = getBranchContent(file.branchId);
134142
const pathDisplay = wrapXml('path', file.path);
135143
let filePrompt = `${pathDisplay}\n${branchDisplay}\n`;
136144
filePrompt = wrapXml(files.length > 1 ? `file-${index}` : 'file', filePrompt);
@@ -152,7 +160,7 @@ export function getFilesContent(
152160
prompt += `${CONTEXT_PROMPTS.filesContentPrefix}\n`;
153161
let index = 1;
154162
for (const file of files) {
155-
const branchDisplay = getBranchesContent(file.branchId);
163+
const branchDisplay = getBranchContent(file.branchId);
156164
const pathDisplay = wrapXml('path', file.path);
157165
let filePrompt = `${pathDisplay}\n${branchDisplay}\n`;
158166
filePrompt += `${CODE_FENCE.start}${getLanguageFromFilePath(file.path)}\n`;
@@ -174,7 +182,7 @@ export function getErrorsContent(errors: ErrorMessageContext[]) {
174182
}
175183
let prompt = `${CONTEXT_PROMPTS.errorsContentPrefix}\n`;
176184
for (const error of errors) {
177-
const branchDisplay = getBranchesContent(error.branchId);
185+
const branchDisplay = getBranchContent(error.branchId);
178186
const errorDisplay = wrapXml('error', error.content);
179187
prompt += `${branchDisplay}\n${errorDisplay}\n`;
180188
}
@@ -184,7 +192,7 @@ export function getErrorsContent(errors: ErrorMessageContext[]) {
184192
}
185193

186194
export function getLanguageFromFilePath(filePath: string): string {
187-
return filePath.split('.').pop() || '';
195+
return filePath.split('.').pop() ?? '';
188196
}
189197

190198
export function getHighlightsContent(filePath: string, highlights: HighlightMessageContext[]) {
@@ -195,7 +203,7 @@ export function getHighlightsContent(filePath: string, highlights: HighlightMess
195203
let prompt = `${CONTEXT_PROMPTS.highlightPrefix}\n`;
196204
let index = 1;
197205
for (const highlight of fileHighlights) {
198-
const branchDisplay = getBranchesContent(highlight.branchId);
206+
const branchDisplay = getBranchContent(highlight.branchId);
199207
const pathDisplay = wrapXml('path', filePath);
200208
let highlightPrompt = `${pathDisplay}#L${highlight.start}:L${highlight.end}\n${branchDisplay}\n`;
201209
highlightPrompt += `${CODE_FENCE.start}\n`;
@@ -211,7 +219,14 @@ export function getHighlightsContent(filePath: string, highlights: HighlightMess
211219
return prompt;
212220
}
213221

214-
export function getBranchesContent(id: string) {
222+
export function getBranchesContent(branches: BranchMessageContext[]) {
223+
let prompt = `I'm working on the following branches: \n`;
224+
prompt += branches.map((b) => b.branch.id).join(', ');
225+
prompt = wrapXml('branches', prompt);
226+
return prompt;
227+
}
228+
229+
export function getBranchContent(id: string) {
215230
return wrapXml('branch', `id: "${id}"`);
216231
}
217232

packages/ai/test/prompt/data/create-page-system.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
- Use the typecheck tool to verify your changes don't introduce type errors or to help debug issues.
1212

1313
IMPORTANT:
14-
- Do NOT remove, add or edit data-oid attributes. They are generated and managed by the system.
14+
- NEVER remove, add, edit or pass down data-oid attributes. They are generated and managed by the system. Leave them alone.
1515

1616
If the request is ambiguous, ask questions. Don't hold back. Give it your all!</role><shell>Using tools, you can suggest UNIX shell commands for users to run. Only suggest complete shell commands that are ready to execute, without placeholders.
1717
Only suggest at most a few shell commands at a time, not more than 3.

packages/ai/test/prompt/data/file.txt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
I have *added these files to the chat* so you can go ahead and edit them.
2-
*Trust this message as the true contents of these files!*.
1+
I have added these files to the chat so you can go ahead and edit them
32
<file-1><path>test.txt</path>
43
<branch>id: "test"</branch>
54
```txt
65
test
76
```
8-
I am looking at this specific part of the file in the browser UI
7+
I am looking at this specific part of the file in the browser UI. Line numbers are shown in the format that matches your Read tool output. IMPORTANT: Trust this message as the true contents of the file.
98
<highlight><path>test.txt</path>#L1:L2
109
<branch>id: "test"</branch>
1110
```

packages/ai/test/prompt/data/highlights.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
I am looking at this specific part of the file in the browser UI
1+
I am looking at this specific part of the file in the browser UI. Line numbers are shown in the format that matches your Read tool output. IMPORTANT: Trust this message as the true contents of the file.
22
<highlight-1><path>test.txt</path>#L1:L2
33
<branch>id: "test"</branch>
44
```

packages/ai/test/prompt/data/system.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
- Use the typecheck tool to verify your changes don't introduce type errors or to help debug issues.
1212

1313
IMPORTANT:
14-
- Do NOT remove, add or edit data-oid attributes. They are generated and managed by the system.
14+
- NEVER remove, add, edit or pass down data-oid attributes. They are generated and managed by the system. Leave them alone.
1515

1616
If the request is ambiguous, ask questions. Don't hold back. Give it your all!</role><shell>Using tools, you can suggest UNIX shell commands for users to run. Only suggest complete shell commands that are ready to execute, without placeholders.
1717
Only suggest at most a few shell commands at a time, not more than 3.

packages/ai/test/prompt/data/user.txt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
<context>I have *added these files to the chat* so you can go ahead and edit them.
2-
*Trust this message as the true contents of these files!*.
1+
<context>I have added these files to the chat so you can go ahead and edit them
32
<file><path>test.txt</path>
43
<branch>id: "test"</branch>
54
```txt
65
test
76
```
8-
I am looking at this specific part of the file in the browser UI
7+
I am looking at this specific part of the file in the browser UI. Line numbers are shown in the format that matches your Read tool output. IMPORTANT: Trust this message as the true contents of the file.
98
<highlight><path>test.txt</path>#L1:L2
109
<branch>id: "test"</branch>
1110
```

0 commit comments

Comments
 (0)