Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit4fd0312

Browse files
authored
feat: use backend-supplied sidebar app id on the /task/$id page (#18458)
Related to#18454. It willclosecoder/internal#734.
1 parent64a2214 commit4fd0312

File tree

5 files changed

+231
-156
lines changed

5 files changed

+231
-156
lines changed

‎site/src/pages/TaskPage/TaskApps.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import { type FC, useState } from "react";
1515
import{LinkasRouterLink}from"react-router-dom";
1616
import{cn}from"utils/cn";
1717
import{TaskAppIFrame}from"./TaskAppIframe";
18-
import{AI_APP_CHAT_SLUG}from"./constants";
1918

2019
typeTaskAppsProps={
2120
task:Task;
@@ -30,7 +29,9 @@ export const TaskApps: FC<TaskAppsProps> = ({ task }) => {
3029
// it here
3130
constapps=agents
3231
.flatMap((a)=>a?.apps)
33-
.filter((a)=>!!a&&a.slug!==AI_APP_CHAT_SLUG);
32+
.filter(
33+
(a)=>!!a&&a.id!==task.workspace.latest_build.ai_task_sidebar_app_id,
34+
);
3435

3536
constembeddedApps=apps.filter((app)=>!app.external);
3637
constexternalApps=apps.filter((app)=>app.external);

‎site/src/pages/TaskPage/TaskPage.stories.tsx

Lines changed: 133 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
importtype{Meta,StoryObj}from"@storybook/react";
22
import{expect,spyOn,within}from"@storybook/test";
3-
importtype{Workspace,WorkspaceApp}from"api/typesGenerated";
3+
importtype{
4+
Workspace,
5+
WorkspaceApp,
6+
WorkspaceResource,
7+
}from"api/typesGenerated";
48
import{
59
MockFailedWorkspace,
610
MockStartingWorkspace,
@@ -13,11 +17,12 @@ import {
1317
mockApiError,
1418
}from"testHelpers/entities";
1519
import{withProxyProvider}from"testHelpers/storybook";
16-
importTaskPage,{data}from"./TaskPage";
20+
importTaskPage,{data,WorkspaceDoesNotHaveAITaskError}from"./TaskPage";
1721

1822
constmeta:Meta<typeofTaskPage>={
1923
title:"pages/TaskPage",
2024
component:TaskPage,
25+
decorators:[withProxyProvider()],
2126
parameters:{
2227
layout:"fullscreen",
2328
},
@@ -96,61 +101,142 @@ export const TerminatedBuildWithStatus: Story = {
96101
},
97102
};
98103

99-
functionactiveWorkspace(apps:WorkspaceApp[]):Workspace{
104+
exportconstSidebarAppDisabled:Story={
105+
beforeEach:()=>{
106+
spyOn(data,"fetchTask").mockResolvedValue({
107+
prompt:"Create competitors page",
108+
workspace:{
109+
...MockWorkspace,
110+
latest_build:{
111+
...MockWorkspace.latest_build,
112+
has_ai_task:true,
113+
ai_task_sidebar_app_id:"claude-code",
114+
resources:mockResources({
115+
claudeCodeAppOverrides:{
116+
health:"disabled",
117+
},
118+
}),
119+
},
120+
},
121+
});
122+
},
123+
};
124+
125+
exportconstSidebarAppLoading:Story={
126+
beforeEach:()=>{
127+
spyOn(data,"fetchTask").mockResolvedValue({
128+
prompt:"Create competitors page",
129+
workspace:{
130+
...MockWorkspace,
131+
latest_build:{
132+
...MockWorkspace.latest_build,
133+
has_ai_task:true,
134+
ai_task_sidebar_app_id:"claude-code",
135+
resources:mockResources({
136+
claudeCodeAppOverrides:{
137+
health:"initializing",
138+
},
139+
}),
140+
},
141+
},
142+
});
143+
},
144+
};
145+
146+
exportconstSidebarAppHealthy:Story={
147+
beforeEach:()=>{
148+
spyOn(data,"fetchTask").mockResolvedValue({
149+
prompt:"Create competitors page",
150+
workspace:{
151+
...MockWorkspace,
152+
latest_build:{
153+
...MockWorkspace.latest_build,
154+
has_ai_task:true,
155+
ai_task_sidebar_app_id:"claude-code",
156+
resources:mockResources({
157+
claudeCodeAppOverrides:{
158+
health:"healthy",
159+
},
160+
}),
161+
},
162+
},
163+
});
164+
},
165+
};
166+
167+
exportconstBuildNoAITask:Story={
168+
beforeEach:()=>{
169+
spyOn(data,"fetchTask").mockImplementation(()=>{
170+
thrownewWorkspaceDoesNotHaveAITaskError(MockWorkspace);
171+
});
172+
},
173+
};
174+
175+
interfaceMockResourcesProps{
176+
apps?:WorkspaceApp[];
177+
claudeCodeAppOverrides?:Partial<WorkspaceApp>;
178+
}
179+
180+
constmockResources=(
181+
props?:MockResourcesProps,
182+
):readonlyWorkspaceResource[]=>[
183+
{
184+
...MockWorkspaceResource,
185+
agents:[
186+
{
187+
...MockWorkspaceAgent,
188+
apps:[
189+
...(props?.apps??[]),
190+
{
191+
...MockWorkspaceApp,
192+
id:"claude-code",
193+
display_name:"Claude Code",
194+
slug:"claude-code",
195+
icon:"/icon/claude.svg",
196+
statuses:[
197+
MockWorkspaceAppStatus,
198+
{
199+
...MockWorkspaceAppStatus,
200+
id:"2",
201+
message:"Planning changes",
202+
state:"working",
203+
},
204+
],
205+
...(props?.claudeCodeAppOverrides??{}),
206+
},
207+
{
208+
...MockWorkspaceApp,
209+
id:"vscode",
210+
slug:"vscode",
211+
display_name:"VS Code Web",
212+
icon:"/icon/code.svg",
213+
},
214+
{
215+
...MockWorkspaceApp,
216+
slug:"zed",
217+
id:"zed",
218+
display_name:"Zed",
219+
icon:"/icon/zed.svg",
220+
},
221+
],
222+
},
223+
],
224+
},
225+
];
226+
227+
constactiveWorkspace=(apps:WorkspaceApp[]):Workspace=>{
100228
return{
101229
...MockWorkspace,
102230
latest_build:{
103231
...MockWorkspace.latest_build,
104-
resources:[
105-
{
106-
...MockWorkspaceResource,
107-
agents:[
108-
{
109-
...MockWorkspaceAgent,
110-
apps:[
111-
...apps,
112-
{
113-
...MockWorkspaceApp,
114-
id:"claude-code",
115-
display_name:"Claude Code",
116-
slug:"claude-code",
117-
icon:"/icon/claude.svg",
118-
statuses:[
119-
MockWorkspaceAppStatus,
120-
{
121-
...MockWorkspaceAppStatus,
122-
id:"2",
123-
message:"Planning changes",
124-
state:"working",
125-
},
126-
],
127-
},
128-
{
129-
...MockWorkspaceApp,
130-
id:"vscode",
131-
slug:"vscode",
132-
display_name:"VS Code Web",
133-
icon:"/icon/code.svg",
134-
},
135-
{
136-
...MockWorkspaceApp,
137-
slug:"zed",
138-
id:"zed",
139-
display_name:"Zed",
140-
icon:"/icon/zed.svg",
141-
},
142-
],
143-
},
144-
],
145-
},
146-
],
232+
resources:mockResources({ apps}),
147233
},
148234
latest_app_status:{
149235
...MockWorkspaceAppStatus,
150236
app_id:"claude-code",
151237
},
152238
};
153-
}
239+
};
154240

155241
exportconstActive:Story={
156242
decorators:[withProxyProvider()],

‎site/src/pages/TaskPage/TaskPage.tsx

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import{API}from"api/api";
22
import{getErrorDetail,getErrorMessage}from"api/errors";
3-
importtype{WorkspaceStatus}from"api/typesGenerated";
3+
importtype{Workspace,WorkspaceStatus}from"api/typesGenerated";
44
import{Button}from"components/Button/Button";
55
import{Loader}from"components/Loader/Loader";
66
import{Margins}from"components/Margins/Margins";
@@ -164,7 +164,7 @@ const TaskPage = () => {
164164
return(
165165
<>
166166
<Helmet>
167-
<title>{pageTitle(ellipsizeText(task.prompt,64)!)}</title>
167+
<title>{pageTitle(ellipsizeText(task.prompt,64)??"Task")}</title>
168168
</Helmet>
169169

170170
<divclassName="h-full flex justify-stretch">
@@ -177,22 +177,34 @@ const TaskPage = () => {
177177

178178
exportdefaultTaskPage;
179179

180+
exportclassWorkspaceDoesNotHaveAITaskErrorextendsError{
181+
constructor(workspace:Workspace){
182+
super(
183+
`Workspace${workspace.owner_name}/${workspace.name} is not running an AI task`,
184+
);
185+
this.name="WorkspaceDoesNotHaveAITaskError";
186+
}
187+
}
188+
180189
exportconstdata={
181190
fetchTask:async(workspaceOwnerUsername:string,workspaceName:string)=>{
182191
constworkspace=awaitAPI.getWorkspaceByOwnerAndName(
183192
workspaceOwnerUsername,
184193
workspaceName,
185194
);
195+
if(
196+
workspace.latest_build.job.completed_at&&
197+
!workspace.latest_build.has_ai_task
198+
){
199+
thrownewWorkspaceDoesNotHaveAITaskError(workspace);
200+
}
201+
186202
constparameters=awaitAPI.getWorkspaceBuildParameters(
187203
workspace.latest_build.id,
188204
);
189-
constprompt=parameters.find(
190-
(p)=>p.name===AI_PROMPT_PARAMETER_NAME,
191-
)?.value;
192-
193-
if(!prompt){
194-
return;
195-
}
205+
constprompt=
206+
parameters.find((p)=>p.name===AI_PROMPT_PARAMETER_NAME)?.value??
207+
"Unknown prompt";
196208

197209
return{
198210
workspace,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp