feat: creating list processor

This commit is contained in:
2025-10-05 15:02:12 +01:00
parent 64abf79f9c
commit 9948d2521b
8 changed files with 53 additions and 41 deletions

View File

@ -21,6 +21,8 @@ and add a good description for each one.
You can add fields if you think they make a lot of sense. You can add fields if you think they make a lot of sense.
You can remove fields if they are not correct, but be sure before you do this. You can remove fields if they are not correct, but be sure before you do this.
You must respond in json format
` `
const listJsonSchema = ` const listJsonSchema = `
@ -79,7 +81,7 @@ type CreateListAgent struct {
stackModel models.StackModel stackModel models.StackModel
} }
func (agent *CreateListAgent) CreateList(log *log.Logger, userID uuid.UUID, title string, userReq string) error { func (agent *CreateListAgent) CreateList(log *log.Logger, userID uuid.UUID, stackID uuid.UUID, title string, userReq string) error {
request := client.AgentRequestBody{ request := client.AgentRequestBody{
Model: "policy/images", Model: "policy/images",
Temperature: 0.3, Temperature: 0.3,
@ -107,6 +109,8 @@ func (agent *CreateListAgent) CreateList(log *log.Logger, userID uuid.UUID, titl
structuredOutput := resp.Choices[0].Message.Content structuredOutput := resp.Choices[0].Message.Content
log.Info("", "res", structuredOutput)
var createListArgs createNewListArguments var createListArgs createNewListArguments
err = json.Unmarshal([]byte(structuredOutput), &createListArgs) err = json.Unmarshal([]byte(structuredOutput), &createListArgs)
if err != nil { if err != nil {
@ -116,6 +120,8 @@ func (agent *CreateListAgent) CreateList(log *log.Logger, userID uuid.UUID, titl
schemaItems := make([]model.SchemaItems, 0) schemaItems := make([]model.SchemaItems, 0)
for _, field := range createListArgs.Fields { for _, field := range createListArgs.Fields {
schemaItems = append(schemaItems, model.SchemaItems{ schemaItems = append(schemaItems, model.SchemaItems{
StackID: stackID,
Item: field.Name, Item: field.Name,
Description: field.Description, Description: field.Description,
@ -123,11 +129,6 @@ func (agent *CreateListAgent) CreateList(log *log.Logger, userID uuid.UUID, titl
}) })
} }
_, err = agent.stackModel.Save(ctx, userID, createListArgs.Title, createListArgs.Description, model.Progress_Complete)
if err != nil {
return fmt.Errorf("creating list agent, saving list: %w", err)
}
err = agent.stackModel.SaveItems(ctx, schemaItems) err = agent.stackModel.SaveItems(ctx, schemaItems)
if err != nil { if err != nil {
return fmt.Errorf("creating list agent, saving items: %w", err) return fmt.Errorf("creating list agent, saving items: %w", err)

View File

@ -9,7 +9,7 @@ import (
const ( const (
IMAGE_TYPE = "image" IMAGE_TYPE = "image"
STACK_TYPE = "list" STACK_TYPE = "stack"
) )
type ImageNotification struct { type ImageNotification struct {

View File

@ -46,7 +46,7 @@ func (p *StackProcessor) setStackToProcess(ctx context.Context, stack model.Stac
} }
func (p *StackProcessor) extractInfo(ctx context.Context, stack model.Stacks) { func (p *StackProcessor) extractInfo(ctx context.Context, stack model.Stacks) {
err := p.stackAgent.CreateList(p.logger, stack.UserID, stack.Name, stack.Description) err := p.stackAgent.CreateList(p.logger, stack.UserID, stack.ID, stack.Name, stack.Description)
if err != nil { if err != nil {
// Again, wtf do we do? // Again, wtf do we do?
// Although i think the agent actually returns an error when it's finished // Although i think the agent actually returns an error when it's finished

View File

@ -41,7 +41,7 @@ func setupRouter(db *sql.DB, jwtManager *ourmiddleware.JwtManager) (chi.Router,
return nil, fmt.Errorf("processor: %w", err) return nil, fmt.Errorf("processor: %w", err)
} }
stackProcessorLog := createLogger("Stack0 Processor", os.Stdout) stackProcessorLog := createLogger("Stack Processor", os.Stdout)
stackProcessor, err := processor.NewStackProcessor(stackProcessorLog, stackModel, &notifier) stackProcessor, err := processor.NewStackProcessor(stackProcessorLog, stackModel, &notifier)
if err != nil { if err != nil {
return nil, fmt.Errorf("processor: %w", err) return nil, fmt.Errorf("processor: %w", err)
@ -50,7 +50,7 @@ func setupRouter(db *sql.DB, jwtManager *ourmiddleware.JwtManager) (chi.Router,
go imageProcessor.Processor.Work() go imageProcessor.Processor.Work()
go stackProcessor.Processor.Work() go stackProcessor.Processor.Work()
stackHandler := stacks.CreateStackHandler(db, limitsManager, jwtManager) stackHandler := stacks.CreateStackHandler(db, limitsManager, jwtManager, stackProcessor.Processor)
authHandler := auth.CreateAuthHandler(db, jwtManager) authHandler := auth.CreateAuthHandler(db, jwtManager)
imageHandler := images.CreateImageHandler(db, limitsManager, jwtManager, imageProcessor.Processor) imageHandler := images.CreateImageHandler(db, limitsManager, jwtManager, imageProcessor.Processor)

View File

@ -8,6 +8,7 @@ import (
"screenmark/screenmark/limits" "screenmark/screenmark/limits"
"screenmark/screenmark/middleware" "screenmark/screenmark/middleware"
"screenmark/screenmark/models" "screenmark/screenmark/models"
"screenmark/screenmark/processor"
"github.com/charmbracelet/log" "github.com/charmbracelet/log"
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
@ -23,6 +24,8 @@ type StackHandler struct {
limitsManager limits.LimitsManagerMethods limitsManager limits.LimitsManagerMethods
jwtManager *middleware.JwtManager jwtManager *middleware.JwtManager
processor *processor.Processor[model.Stacks]
} }
func (h *StackHandler) getAllStacks(w http.ResponseWriter, r *http.Request) { func (h *StackHandler) getAllStacks(w http.ResponseWriter, r *http.Request) {
@ -216,6 +219,8 @@ func (h *StackHandler) createStack(body CreateStackBody, w http.ResponseWriter,
return return
} }
h.processor.Add(stack)
middleware.WriteJsonOrError(h.logger, stack, w) middleware.WriteJsonOrError(h.logger, stack, w)
} }
@ -237,7 +242,12 @@ func (h *StackHandler) CreateRoutes(r chi.Router) {
}) })
} }
func CreateStackHandler(db *sql.DB, limitsManager limits.LimitsManagerMethods, jwtManager *middleware.JwtManager) StackHandler { func CreateStackHandler(
db *sql.DB,
limitsManager limits.LimitsManagerMethods,
jwtManager *middleware.JwtManager,
processor *processor.Processor[model.Stacks],
) StackHandler {
stackModel := models.NewStackModel(db) stackModel := models.NewStackModel(db)
imageModel := models.NewImageModel(db) imageModel := models.NewImageModel(db)
logger := log.New(os.Stdout).WithPrefix("Stacks") logger := log.New(os.Stdout).WithPrefix("Stacks")
@ -248,5 +258,6 @@ func CreateStackHandler(db *sql.DB, limitsManager limits.LimitsManagerMethods, j
stackModel: stackModel, stackModel: stackModel,
limitsManager: limitsManager, limitsManager: limitsManager,
jwtManager: jwtManager, jwtManager: jwtManager,
processor: processor,
} }
} }

View File

@ -9,7 +9,7 @@ export const ProcessingImages: Component = () => {
const processingNumber = () => const processingNumber = () =>
Object.keys(notifications.state.ProcessingImages).length + Object.keys(notifications.state.ProcessingImages).length +
Object.keys(notifications.state.ProcessingLists).length; Object.keys(notifications.state.ProcessingStacks).length;
const [accessToken] = createResource(getAccessToken) const [accessToken] = createResource(getAccessToken)
@ -60,13 +60,13 @@ export const ProcessingImages: Component = () => {
)} )}
</For> </For>
<For each={Object.entries(notifications.state.ProcessingLists)}> <For each={Object.entries(notifications.state.ProcessingStacks)}>
{([, _list]) => ( {([, _stack]) => (
<Show when={_list}> <Show when={_stack}>
{(list) => ( {(stack) => (
<div class="flex gap-2 w-full justify-center"> <div class="flex gap-2 w-full justify-center">
<div class="flex flex-col gap-1"> <div class="flex flex-col gap-1">
<p class="text-slate-900">New Stack: {list().Name}</p> <p class="text-slate-900">New Stack: {stack().Name}</p>
</div> </div>
<LoadingCircle <LoadingCircle
status="loading" status="loading"

View File

@ -22,7 +22,7 @@ type NotificationState = {
string, string,
InferOutput<typeof processingImagesValidator> | undefined InferOutput<typeof processingImagesValidator> | undefined
>; >;
ProcessingLists: Record< ProcessingStacks: Record<
string, string,
InferOutput<typeof processingListValidator> | undefined InferOutput<typeof processingListValidator> | undefined
>; >;
@ -31,7 +31,7 @@ type NotificationState = {
export const Notifications = (onCompleteImage: () => void) => { export const Notifications = (onCompleteImage: () => void) => {
const [state, setState] = createStore<NotificationState>({ const [state, setState] = createStore<NotificationState>({
ProcessingImages: {}, ProcessingImages: {},
ProcessingLists: {}, ProcessingStacks: {},
}); });
const { userImages } = useSearchImageContext(); const { userImages } = useSearchImageContext();
@ -71,14 +71,14 @@ export const Notifications = (onCompleteImage: () => void) => {
} else { } else {
setState("ProcessingImages", ImageID, notification.output); setState("ProcessingImages", ImageID, notification.output);
} }
} else if (notification.output.Type === "list") { } else if (notification.output.Type === "stack") {
const { ListID, Status } = notification.output; const { StackID, Status } = notification.output;
if (Status === "complete") { if (Status === "complete") {
setState("ProcessingLists", ListID, undefined); setState("ProcessingStacks", StackID, undefined);
onCompleteImage(); onCompleteImage();
} else { } else {
setState("ProcessingLists", ListID, notification.output); setState("ProcessingStacks", StackID, notification.output);
} }
} }
}; };

View File

@ -1,31 +1,31 @@
import { literal, pipe, strictObject, string, union, uuid } from "valibot"; import { literal, pipe, strictObject, string, union, uuid } from "valibot";
export const processingListValidator = strictObject({ export const processingListValidator = strictObject({
Type: literal("list"), Type: literal("stack"),
Name: string(), Name: string(),
ListID: pipe(string(), uuid()), StackID: pipe(string(), uuid()),
Status: union([ Status: union([
literal("not-started"), literal("not-started"),
literal("in-progress"), literal("in-progress"),
literal("complete"), literal("complete"),
]), ]),
}); });
export const processingImagesValidator = strictObject({ export const processingImagesValidator = strictObject({
Type: literal("image"), Type: literal("image"),
ImageID: pipe(string(), uuid()), ImageID: pipe(string(), uuid()),
ImageName: string(), ImageName: string(),
Status: union([ Status: union([
literal("not-started"), literal("not-started"),
literal("in-progress"), literal("in-progress"),
literal("complete"), literal("complete"),
]), ]),
}); });
export const notificationValidator = union([ export const notificationValidator = union([
processingListValidator, processingListValidator,
processingImagesValidator, processingImagesValidator,
]); ]);