Skip to content

Commit b70072e

Browse files
committed
Enhance: Allow project to be upgraded when drift changes detected
Signed-off-by: Daishan Peng <[email protected]>
1 parent e97d8f5 commit b70072e

File tree

6 files changed

+67
-41
lines changed

6 files changed

+67
-41
lines changed

apiclient/types/project.go

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,17 @@ package types
33
type Project struct {
44
Metadata
55
ProjectManifest
6-
AssistantID string `json:"assistantID,omitempty"`
7-
Editor bool `json:"editor"`
8-
ParentID string `json:"parentID,omitempty"`
9-
SourceProjectID string `json:"sourceProjectID,omitempty"`
10-
UserID string `json:"userID,omitempty"`
11-
WorkflowNamesFromIntegration WorkflowNamesFromIntegration `json:"workflowNamesFromIntegration,omitempty"`
12-
TemplateUpgradeAvailable bool `json:"templateUpgradeAvailable,omitempty"`
13-
TemplateUpgradeInProgress bool `json:"templateUpgradeInProgress,omitempty"`
14-
TemplateLastUpgraded *Time `json:"templateLastUpgraded,omitempty"`
15-
TemplatePublicID string `json:"templatePublicID,omitempty"`
6+
AssistantID string `json:"assistantID,omitempty"`
7+
Editor bool `json:"editor"`
8+
ParentID string `json:"parentID,omitempty"`
9+
SourceProjectID string `json:"sourceProjectID,omitempty"`
10+
UserID string `json:"userID,omitempty"`
11+
WorkflowNamesFromIntegration WorkflowNamesFromIntegration `json:"workflowNamesFromIntegration,omitempty"`
12+
TemplateUpgradeAvailable bool `json:"templateUpgradeAvailable,omitempty"`
13+
TemplateForceUpgradeAvailable bool `json:"templateForceUpgradeAvailable,omitempty"`
14+
TemplateUpgradeInProgress bool `json:"templateUpgradeInProgress,omitempty"`
15+
TemplateLastUpgraded *Time `json:"templateLastUpgraded,omitempty"`
16+
TemplatePublicID string `json:"templatePublicID,omitempty"`
1617
}
1718

1819
type WorkflowNamesFromIntegration struct {

pkg/api/handlers/projects.go

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -268,13 +268,6 @@ func (h *ProjectsHandler) UpgradeFromTemplate(req api.Context) error {
268268
return types.NewErrHTTP(http.StatusTooEarly, "project upgrade already in progress")
269269
}
270270

271-
if !thread.Status.UpgradeAvailable {
272-
// Project is ineligable for an upgrade due to one of the following reasons:
273-
// - the project is already at the latest revision of the project snapshot
274-
// - the user has manually modified the project
275-
return types.NewErrBadRequest("project not eligible for an upgrade")
276-
}
277-
278271
if thread.Spec.UpgradeApproved {
279272
// Project is already approved for an upgrade, nothing to do
280273
return nil
@@ -518,15 +511,16 @@ func convertProject(thread *v1.Thread, parentThread *v1.Thread) types.Project {
518511
Models: thread.Spec.Models,
519512
Capabilities: convertProjectCapabilities(thread.Spec.Capabilities),
520513
},
521-
ParentID: strings.Replace(thread.Spec.ParentThreadName, system.ThreadPrefix, system.ProjectPrefix, 1),
522-
SourceProjectID: strings.Replace(thread.Spec.SourceThreadName, system.ThreadPrefix, system.ProjectPrefix, 1),
523-
AssistantID: thread.Spec.AgentName,
524-
Editor: thread.IsEditor(),
525-
UserID: thread.Spec.UserID,
526-
WorkflowNamesFromIntegration: thread.Status.WorkflowNamesFromIntegration,
527-
TemplateUpgradeAvailable: (thread.Status.UpgradeAvailable && !thread.Spec.UpgradeApproved),
528-
TemplateUpgradeInProgress: thread.Status.UpgradeInProgress,
529-
TemplatePublicID: thread.Status.UpgradePublicID,
514+
ParentID: strings.Replace(thread.Spec.ParentThreadName, system.ThreadPrefix, system.ProjectPrefix, 1),
515+
SourceProjectID: strings.Replace(thread.Spec.SourceThreadName, system.ThreadPrefix, system.ProjectPrefix, 1),
516+
AssistantID: thread.Spec.AgentName,
517+
Editor: thread.IsEditor(),
518+
UserID: thread.Spec.UserID,
519+
WorkflowNamesFromIntegration: thread.Status.WorkflowNamesFromIntegration,
520+
TemplateUpgradeAvailable: (thread.Status.UpgradeAvailable && !thread.Spec.UpgradeApproved),
521+
TemplateForceUpgradeAvailable: thread.Status.ForceUpgradeAvailable,
522+
TemplateUpgradeInProgress: thread.Status.UpgradeInProgress,
523+
TemplatePublicID: thread.Status.UpgradePublicID,
530524
}
531525

532526
if !thread.Status.LastUpgraded.IsZero() {

pkg/controller/handlers/threads/template.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@ func (t *Handler) EnsureUpgradeAvailable(req router.Request, _ router.Response)
3232
}
3333

3434
var (
35-
source v1.Thread
36-
upgradeAvailable bool
35+
source v1.Thread
36+
upgradeAvailable bool
37+
forceUpgradeAvailable bool
3738
)
3839
if err := req.Client.Get(req.Ctx, router.Key(thread.Namespace, thread.Spec.SourceThreadName), &source); err != nil {
3940
if !apierrors.IsNotFound(err) {
@@ -53,18 +54,22 @@ func (t *Handler) EnsureUpgradeAvailable(req router.Request, _ router.Response)
5354
// If we find the revision, but it's the latest revision, there's no new upgrade available.
5455
found, latest := source.HasRevision(thread.GetLatestConfigRevision())
5556
upgradeAvailable = found && !latest
57+
58+
// if the thread's latest revision is not in the source thread's history, then we provide a status to show option to force upgrade
59+
forceUpgradeAvailable = !found
5660
}
5761

5862
upgradeAvailable = !source.Status.UpgradeInProgress && upgradeAvailable
5963
}
6064

61-
if thread.Status.UpgradeAvailable == upgradeAvailable {
65+
if thread.Status.UpgradeAvailable == upgradeAvailable && thread.Status.ForceUpgradeAvailable == forceUpgradeAvailable {
6266
// No change, bail out
6367
return nil
6468
}
6569

6670
// Update the status with the new value
6771
thread.Status.UpgradeAvailable = upgradeAvailable
72+
thread.Status.ForceUpgradeAvailable = forceUpgradeAvailable
6873
return req.Client.Status().Update(req.Ctx, thread)
6974
}
7075

pkg/storage/apis/obot.obot.ai/v1/thread.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,9 @@ type ThreadStatus struct {
330330
// into this thread AND the thread's configuration has not changed since it was copied.
331331
UpgradeAvailable bool `json:"upgradeAvailable,omitempty"`
332332

333+
// ForceUpgradeAvailable is a flag to indicate if an force upgrade is available from the source thread.
334+
ForceUpgradeAvailable bool `json:"forceUpgradeAvailable,omitempty"`
335+
333336
// UpgradeInProgress indicates if an upgrade from the source thread is in progress.
334337
UpgradeInProgress bool `json:"upgradeInProgress,omitempty"`
335338

ui/user/src/lib/components/edit/ProjectConfiguration.svelte

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<script lang="ts">
22
import { closeAll, getLayout } from '$lib/context/chatLayout.svelte';
33
import { ChatService, type Project } from '$lib/services';
4-
import { LoaderCircle, X, AlertCircle, CircleFadingArrowUp } from 'lucide-svelte';
4+
import { LoaderCircle, X, CircleFadingArrowUp } from 'lucide-svelte';
55
import { HELPER_TEXTS } from '$lib/context/helperMode.svelte';
66
import Memories from '$lib/components/edit/Memories.svelte';
77
import { getProjectTools } from '$lib/context/projectTools.svelte';
@@ -41,6 +41,12 @@
4141
project.templateUpgradeAvailable &&
4242
shareUrl
4343
);
44+
let showForceUpgradeButton = $derived(
45+
!!project?.sourceProjectID &&
46+
project.sourceProjectID.trim() !== '' &&
47+
project.templateForceUpgradeAvailable &&
48+
shareUrl
49+
);
4450
4551
async function upgradeFromTemplate() {
4652
upgradeLoading = true;
@@ -166,21 +172,37 @@
166172
<CircleFadingArrowUp class="relative top-[1px] size-4 shrink-0" />
167173
{/if}
168174
</button>
175+
{:else if showForceUpgradeButton}
176+
<button
177+
class="button flex gap-1"
178+
onclick={upgradeFromTemplate}
179+
disabled={upgradeLoading}
180+
title="This will override any manual changes and upgrade to the latest revision"
181+
>
182+
{#if upgradeLoading}
183+
<LoaderCircle class="size-4 animate-spin" />
184+
{:else}
185+
Force Upgrade
186+
<CircleFadingArrowUp class="relative top-[1px] size-4 shrink-0" />
187+
{/if}
188+
</button>
169189
{/if}
170190
</div>
171191
</div>
172192
{/if}
173-
174-
<p
175-
class="mt-1 flex w-full items-center justify-center gap-1 text-center text-xs font-light text-gray-600"
176-
>
177-
<AlertCircle class="max-h-3.5 min-h-3.5" />
178-
<span>
179-
Changing fields such as instructions, MCP servers, tasks, or knowledge will make
180-
this project ineligible to receive updates from the shared project snapshot
181-
author.
182-
</span>
183-
</p>
193+
{#if showForceUpgradeButton}
194+
<p
195+
class="mt-2 flex w-full items-center justify-center gap-1 text-center text-xs font-light text-yellow-500"
196+
>
197+
<AlertTriangle class="max-h-3.5 min-h-3.5" />
198+
<span>
199+
Our system has detected that you have made changes to this project that are
200+
launched from a template. Clicking on Force Upgrade will override any changes
201+
that were made manually and upgrade to the latest revision of the original
202+
project template.
203+
</span>
204+
</p>
205+
{/if}
184206
</div>
185207
</div>
186208
</div>

ui/user/src/lib/services/chat/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,7 @@ export interface Project {
518518
userID: string;
519519
workflowNamesFromIntegration?: WorkflowNamesFromIntegration;
520520
templateUpgradeAvailable?: boolean;
521+
templateForceUpgradeAvailable?: boolean;
521522
templateUpgradeInProgress?: boolean;
522523
templateLastUpgraded?: string;
523524
templatePublicID?: string;

0 commit comments

Comments
 (0)