Skip to content

Commit 7b99b80

Browse files
authored
more misc builder improvements (#2592)
1 parent 1f48356 commit 7b99b80

File tree

9 files changed

+93
-29
lines changed

9 files changed

+93
-29
lines changed

frontend/app/aipanel/aipanelinput.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ interface AIPanelInputProps {
1717
export interface AIPanelInputRef {
1818
focus: () => void;
1919
resize: () => void;
20+
scrollToBottom: () => void;
2021
}
2122

2223
export const AIPanelInput = memo(({ onSubmit, status, model }: AIPanelInputProps) => {
@@ -43,6 +44,12 @@ export const AIPanelInput = memo(({ onSubmit, status, model }: AIPanelInputProps
4344
textareaRef.current?.focus();
4445
},
4546
resize: resizeTextarea,
47+
scrollToBottom: () => {
48+
const textarea = textareaRef.current;
49+
if (textarea) {
50+
textarea.scrollTop = textarea.scrollHeight;
51+
}
52+
},
4653
},
4754
};
4855
model.registerInputRef(inputRefObject);

frontend/app/aipanel/waveai-model.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ export class WaveAIModel {
301301
return input != null && input.trim().length > 0;
302302
}
303303

304-
appendText(text: string, newLine?: boolean) {
304+
appendText(text: string, newLine?: boolean, opts?: { scrollToBottom?: boolean }) {
305305
const currentInput = globalStore.get(this.inputAtom);
306306
let newInput = currentInput;
307307

@@ -317,6 +317,10 @@ export class WaveAIModel {
317317

318318
newInput += text;
319319
globalStore.set(this.inputAtom, newInput);
320+
321+
if (opts?.scrollToBottom && this.inputRef?.current) {
322+
setTimeout(() => this.inputRef.current.scrollToBottom(), 10);
323+
}
320324
}
321325

322326
setModel(model: string) {

frontend/builder/builder-buildpanel.tsx

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,24 @@ const BuilderBuildPanel = memo(() => {
8282
BuilderAppPanelModel.getInstance().restartBuilder();
8383
}, []);
8484

85-
const filteredLines = showDebug ? outputLines : outputLines.filter((line) => !line.startsWith("[debug]") && line.trim().length > 0);
85+
const handleSendToAI = useCallback(() => {
86+
const currentShowDebug = globalStore.get(model.showDebug);
87+
const currentOutputLines = globalStore.get(model.outputLines);
88+
const filtered = currentShowDebug
89+
? currentOutputLines
90+
: currentOutputLines.filter((line) => !line.startsWith("[debug]") && line.trim().length > 0);
91+
92+
const linesToSend = filtered.slice(-200);
93+
const text = linesToSend.join("\n");
94+
const aiModel = WaveAIModel.getInstance();
95+
const formattedText = `from builder output:\n\`\`\`\n${text}\n\`\`\`\n`;
96+
aiModel.appendText(formattedText, true, { scrollToBottom: true });
97+
aiModel.focusInput();
98+
}, [model]);
99+
100+
const filteredLines = showDebug
101+
? outputLines
102+
: outputLines.filter((line) => !line.startsWith("[debug]") && line.trim().length > 0);
86103

87104
return (
88105
<div className="w-full h-full flex flex-col bg-black rounded-br-2">
@@ -98,6 +115,12 @@ const BuilderBuildPanel = memo(() => {
98115
/>
99116
Debug
100117
</label>
118+
<button
119+
className="px-3 py-1 text-sm font-medium rounded transition-colors bg-accent/80 text-white hover:bg-accent cursor-pointer"
120+
onClick={handleSendToAI}
121+
>
122+
Send Output to AI
123+
</button>
101124
<button
102125
className="px-3 py-1 text-sm font-medium rounded transition-colors bg-accent/80 text-white hover:bg-accent cursor-pointer"
103126
onClick={handleRestart}

frontend/builder/tabs/builder-configdatatab.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ const BuilderConfigDataTab = memo(() => {
6969
const model = BuilderAppPanelModel.getInstance();
7070
const builderStatus = useAtomValue(model.builderStatusAtom);
7171
const builderId = useAtomValue(atoms.builderId);
72+
const activeTab = useAtomValue(model.activeTab);
7273
const [state, setState] = useState<ConfigDataState>({
7374
config: null,
7475
data: null,
@@ -144,17 +145,17 @@ const BuilderConfigDataTab = memo(() => {
144145
}, [state.data]);
145146

146147
useEffect(() => {
147-
if (isRunning) {
148+
if (activeTab === "configdata" && isRunning) {
148149
fetchData();
149-
} else {
150+
} else if (!isRunning) {
150151
setState({
151152
config: null,
152153
data: null,
153154
error: null,
154155
isLoading: false,
155156
});
156157
}
157-
}, [isRunning, fetchData]);
158+
}, [activeTab, isRunning, fetchData]);
158159

159160
if (!isRunning) {
160161
return <NotRunningView />;

pkg/aiusechat/anthropic/anthropic-convertmessage.go

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,18 +72,32 @@ func buildAnthropicHTTPRequest(ctx context.Context, msgs []anthropicInputMessage
7272
}
7373
}
7474

75-
// inject chatOpts.AppGoFile as a "text" block at the END of the LAST "user" message found (append to Content)
76-
if chatOpts.AppGoFile != "" {
75+
// inject chatOpts.PlatformInfo, AppStaticFiles, and AppGoFile as "text" blocks at the END of the LAST "user" message found (append to Content)
76+
if chatOpts.PlatformInfo != "" || chatOpts.AppStaticFiles != "" || chatOpts.AppGoFile != "" {
7777
// Find the last "user" message
7878
for i := len(convertedMsgs) - 1; i >= 0; i-- {
7979
if convertedMsgs[i].Role == "user" {
80-
// Create a text block with the AppGoFile content wrapped in XML tag
81-
appGoFileBlock := anthropicMessageContentBlock{
82-
Type: "text",
83-
Text: "<CurrentAppGoFile>\n" + chatOpts.AppGoFile + "\n</CurrentAppGoFile>",
80+
if chatOpts.PlatformInfo != "" {
81+
platformInfoBlock := anthropicMessageContentBlock{
82+
Type: "text",
83+
Text: "<PlatformInfo>\n" + chatOpts.PlatformInfo + "\n</PlatformInfo>",
84+
}
85+
convertedMsgs[i].Content = append(convertedMsgs[i].Content, platformInfoBlock)
86+
}
87+
if chatOpts.AppStaticFiles != "" {
88+
appStaticFilesBlock := anthropicMessageContentBlock{
89+
Type: "text",
90+
Text: "<CurrentAppStaticFiles>\n" + chatOpts.AppStaticFiles + "\n</CurrentAppStaticFiles>",
91+
}
92+
convertedMsgs[i].Content = append(convertedMsgs[i].Content, appStaticFilesBlock)
93+
}
94+
if chatOpts.AppGoFile != "" {
95+
appGoFileBlock := anthropicMessageContentBlock{
96+
Type: "text",
97+
Text: "<CurrentAppGoFile>\n" + chatOpts.AppGoFile + "\n</CurrentAppGoFile>",
98+
}
99+
convertedMsgs[i].Content = append(convertedMsgs[i].Content, appGoFileBlock)
84100
}
85-
// Append to the Content of this message
86-
convertedMsgs[i].Content = append(convertedMsgs[i].Content, appGoFileBlock)
87101
break
88102
}
89103
}

pkg/aiusechat/openai/openai-convertmessage.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,9 @@ func buildOpenAIHTTPRequest(ctx context.Context, inputs []any, chatOpts uctypes.
218218
if chatOpts.TabState != "" {
219219
appendToLastUserMessage(inputs, chatOpts.TabState)
220220
}
221+
if chatOpts.PlatformInfo != "" {
222+
appendToLastUserMessage(inputs, "<PlatformInfo>\n"+chatOpts.PlatformInfo+"\n</PlatformInfo>")
223+
}
221224
if chatOpts.AppStaticFiles != "" {
222225
appendToLastUserMessage(inputs, "<CurrentAppStaticFiles>\n"+chatOpts.AppStaticFiles+"\n</CurrentAppStaticFiles>")
223226
}

pkg/aiusechat/uctypes/usechat-types.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,7 @@ type WaveChatOpts struct {
449449
Tools []ToolDefinition
450450
SystemPrompt []string
451451
TabStateGenerator func() (string, []ToolDefinition, string, error)
452-
BuilderAppGenerator func() (string, string, error)
452+
BuilderAppGenerator func() (string, string, string, error)
453453
WidgetAccess bool
454454
RegisterToolApproval func(string)
455455
AllowNativeWebSearch bool
@@ -462,6 +462,7 @@ type WaveChatOpts struct {
462462
TabId string
463463
AppGoFile string
464464
AppStaticFiles string
465+
PlatformInfo string
465466
}
466467

467468
func (opts *WaveChatOpts) GetToolDefinition(toolName string) *ToolDefinition {

pkg/aiusechat/usechat.go

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"log"
1212
"net/http"
1313
"os"
14+
"os/user"
1415
"strings"
1516
"sync"
1617
"time"
@@ -411,10 +412,11 @@ func RunAIChat(ctx context.Context, sseHandler *sse.SSEHandlerCh, backend UseCha
411412
}
412413
}
413414
if chatOpts.BuilderAppGenerator != nil {
414-
appGoFile, appStaticFiles, appErr := chatOpts.BuilderAppGenerator()
415+
appGoFile, appStaticFiles, platformInfo, appErr := chatOpts.BuilderAppGenerator()
415416
if appErr == nil {
416417
chatOpts.AppGoFile = appGoFile
417418
chatOpts.AppStaticFiles = appStaticFiles
419+
chatOpts.PlatformInfo = platformInfo
418420
}
419421
}
420422
stopReason, rtnMessage, err := runAIChatStep(ctx, sseHandler, backend, chatOpts, cont)
@@ -689,7 +691,7 @@ func WaveAIPostMessageHandler(w http.ResponseWriter, r *http.Request) {
689691
}
690692

691693
if req.BuilderAppId != "" {
692-
chatOpts.BuilderAppGenerator = func() (string, string, error) {
694+
chatOpts.BuilderAppGenerator = func() (string, string, string, error) {
693695
return generateBuilderAppData(req.BuilderAppId)
694696
}
695697
}
@@ -830,7 +832,7 @@ type StaticFileInfo struct {
830832
ModifiedTime string `json:"modified_time"`
831833
}
832834

833-
func generateBuilderAppData(appId string) (string, string, error) {
835+
func generateBuilderAppData(appId string) (string, string, string, error) {
834836
appGoFile := ""
835837
fileData, err := waveappstore.ReadAppFile(appId, "app.go")
836838
if err == nil {
@@ -860,5 +862,12 @@ func generateBuilderAppData(appId string) (string, string, error) {
860862
}
861863
}
862864

863-
return appGoFile, staticFilesJSON, nil
865+
platformInfo := wavebase.GetSystemSummary()
866+
if currentUser, userErr := user.Current(); userErr == nil && currentUser.Username != "" {
867+
platformInfo = fmt.Sprintf("Local Machine: %s, User: %s", platformInfo, currentUser.Username)
868+
} else {
869+
platformInfo = fmt.Sprintf("Local Machine: %s", platformInfo)
870+
}
871+
872+
return appGoFile, staticFilesJSON, platformInfo, nil
864873
}

pkg/buildercontroller/buildercontroller.go

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,19 @@ func (bc *BuilderController) buildAndRun(ctx context.Context, appId string, buil
261261
return
262262
}
263263

264+
process, err := bc.runBuilderApp(ctx, appId, cachePath, builderEnv)
265+
if err != nil {
266+
bc.handleBuildError(fmt.Errorf("failed to run app: %w", err), resultCh)
267+
return
268+
}
269+
270+
bc.lock.Lock()
271+
bc.process = process
272+
bc.setStatus_nolock(BuilderStatus_Running, process.Port, 0, "")
273+
bc.lock.Unlock()
274+
275+
time.Sleep(1 * time.Second)
276+
264277
if resultCh != nil {
265278
buildOutput := ""
266279
if bc.outputBuffer != nil {
@@ -276,17 +289,6 @@ func (bc *BuilderController) buildAndRun(ctx context.Context, appId string, buil
276289
}
277290
}
278291

279-
process, err := bc.runBuilderApp(ctx, appId, cachePath, builderEnv)
280-
if err != nil {
281-
bc.handleBuildError(fmt.Errorf("failed to run app: %w", err), resultCh)
282-
return
283-
}
284-
285-
bc.lock.Lock()
286-
bc.process = process
287-
bc.setStatus_nolock(BuilderStatus_Running, process.Port, 0, "")
288-
bc.lock.Unlock()
289-
290292
go func() {
291293
<-process.WaitCh
292294
bc.lock.Lock()

0 commit comments

Comments
 (0)