Skip to content

Commit 3662209

Browse files
committed
wip: templates reloaded
Signed-off-by: Nick Hale <[email protected]>
1 parent 9e9e9cb commit 3662209

File tree

22 files changed

+650
-1190
lines changed

22 files changed

+650
-1190
lines changed

apiclient/types/template.go

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package types
22

33
type ProjectTemplate struct {
44
Metadata
5-
ProjectTemplateManifest
65
ProjectSnapshot ThreadManifest `json:"projectSnapshot,omitempty"`
76
MCPServers []string `json:"mcpServers,omitempty"`
87
AssistantID string `json:"assistantID,omitempty"`
@@ -11,10 +10,4 @@ type ProjectTemplate struct {
1110
Ready bool `json:"ready,omitempty"`
1211
}
1312

14-
type ProjectTemplateManifest struct {
15-
Name string `json:"name,omitempty"`
16-
Public bool `json:"public,omitempty"`
17-
Featured bool `json:"featured,omitempty"`
18-
}
19-
2013
type ProjectTemplateList List[ProjectTemplate]

apiclient/types/zz_generated.deepcopy.go

Lines changed: 0 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/api/authz/resources.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -108,11 +108,9 @@ var apiResources = []string{
108108
"GET /api/assistants/{assistant_id}/projects/{project_id}/tasks/{task_id}/runs/{run_id}/files/{file...}",
109109
"POST /api/assistants/{assistant_id}/projects/{project_id}/tasks/{task_id}/runs/{run_id}/files/{file...}",
110110
"POST /api/assistants/{assistant_id}/projects/{project_id}/tasks/{task_id}/runs/{run_id}/steps/{step_id}/run",
111-
"PUT /api/assistants/{assistant_id}/projects/{project_id}/templates/{template_id}",
112-
"DELETE /api/assistants/{assistant_id}/projects/{project_id}/templates/{template_id}",
113-
"GET /api/assistants/{assistant_id}/projects/{project_id}/templates/{template_id}",
114-
"POST /api/assistants/{assistant_id}/projects/{project_id}/templates",
115-
"GET /api/assistants/{assistant_id}/projects/{project_id}/templates",
111+
"POST /api/assistants/{assistant_id}/projects/{project_id}/template",
112+
"GET /api/assistants/{assistant_id}/projects/{project_id}/template",
113+
"DELETE /api/assistants/{assistant_id}/projects/{project_id}/template",
116114
"GET /api/assistants/{assistant_id}/projects/{project_id}/threads",
117115
"POST /api/assistants/{assistant_id}/projects/{project_id}/threads",
118116
"DELETE /api/assistants/{assistant_id}/projects/{project_id}/threads/{thread_id}",
@@ -149,6 +147,7 @@ var apiResources = []string{
149147
"GET /api/assistants/{assistant_id}/projects/{project_id}/tools/{tool_id}/local-authenticate",
150148
"DELETE /api/assistants/{assistant_id}/projects/{project_id}/tools/{tool_id}/local-deauthenticate",
151149
"POST /api/assistants/{assistant_id}/projects/{project_id}/tools/{tool_id}/test",
150+
"POST /api/assistants/{assistant_id}/projects/{project_id}/template-upgrade",
152151
"GET /api/mcp-server-instances",
153152
"GET /api/mcp-server-instances/{mcp_server_instance_id}",
154153
"POST /api/mcp-server-instances",
@@ -265,6 +264,7 @@ func (a *Authorizer) evaluateResources(req *http.Request, vars GetVar, user user
265264
MCPID: vars("mcp_id"), // this will be either a server ID or a server instance ID
266265
PendingAuthorizationID: vars("pending_authorization_id"),
267266
ThreadShareID: vars("share_public_id"),
267+
TemplateID: vars("template_public_id"), // for /api/templates/{template_public_id} routes
268268
ToolID: vars("tool_id"),
269269
}
270270

pkg/api/authz/template.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,18 @@ import (
99
)
1010

1111
func (a *Authorizer) checkTemplate(req *http.Request, resources *Resources) (bool, error) {
12+
// For project-scoped template routes (/api/assistants/{assistant_id}/projects/{project_id}/template),
13+
// authorization is handled by the project check, not a separate template check
1214
if resources.TemplateID == "" {
1315
return true, nil
1416
}
1517

18+
// For global template routes (/api/templates/{template_public_id}),
19+
// check if the template exists and is publicly accessible
1620
var templateShareList v1.ThreadShareList
1721
err := a.cache.List(req.Context(), &templateShareList, kclient.InNamespace(system.DefaultNamespace), kclient.MatchingFields{
1822
"spec.publicID": resources.TemplateID,
23+
"spec.template": "true",
1924
})
2025

2126
return len(templateShareList.Items) > 0, err

pkg/api/handlers/projects.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,44 @@ func (h *ProjectsHandler) GetProject(req api.Context) error {
247247
return req.Write(convertProject(&thread, nil))
248248
}
249249

250+
func (h *ProjectsHandler) TemplateUpgrade(req api.Context) error {
251+
var (
252+
projectID = strings.Replace(req.PathValue("project_id"), system.ProjectPrefix, system.ThreadPrefix, 1)
253+
thread v1.Thread
254+
)
255+
256+
if err := req.Get(&thread, projectID); err != nil {
257+
return err
258+
}
259+
260+
if thread.Spec.SourceThreadName == "" || !thread.Spec.Project {
261+
return types.NewErrBadRequest("project was not created from a template")
262+
}
263+
264+
// Get the source thread to verify it's a template
265+
var source v1.Thread
266+
if err := req.Get(&source, thread.Spec.SourceThreadName); err != nil {
267+
return err
268+
}
269+
270+
// Verify the source is actually a template
271+
if !source.Spec.Template {
272+
return types.NewErrBadRequest("source project is not a template")
273+
}
274+
275+
if thread.Annotations == nil {
276+
thread.Annotations = map[string]string{}
277+
}
278+
// Trigger project refresh in controller to re-copy tools and MCP servers
279+
thread.Annotations["obot.obot.ai/copy-source"] = "true"
280+
281+
if err := req.Update(&thread); err != nil {
282+
return err
283+
}
284+
285+
return nil
286+
}
287+
250288
func (h *ProjectsHandler) ListProjects(req api.Context) error {
251289
var (
252290
assistantID = req.PathValue("assistant_id")

0 commit comments

Comments
 (0)