Canvas: Implement Agent Sketch node, update dodo-app.jsonschema

- Add Gemini API key to the project
- Update dodo schema to support Gemini API key
- Update dodo schema to support Agent Sketch node

Change-Id: I6a96186f86ad169152ca0021b38130e485ebbf14
diff --git a/apps/canvas/back/src/index.ts b/apps/canvas/back/src/index.ts
index 82e55fe..4190f70 100644
--- a/apps/canvas/back/src/index.ts
+++ b/apps/canvas/back/src/index.ts
@@ -322,6 +322,7 @@
 				deployKey: true,
 				deployKeyPublic: true,
 				state: true,
+				geminiApiKey: true,
 			},
 		});
 		if (p === null) {
@@ -376,6 +377,7 @@
 					public: deployKeyPublic!,
 					private: deployKey!,
 				},
+				geminiApiKey: p.geminiApiKey ?? undefined,
 			},
 		};
 		try {
@@ -594,14 +596,34 @@
 
 const handleUpdateGithubToken: express.Handler = async (req, resp) => {
 	try {
-		const projectId = Number(req.params["projectId"]);
-		const { githubToken } = req.body;
 		await db.project.update({
 			where: {
-				id: projectId,
+				id: Number(req.params["projectId"]),
 				userId: resp.locals.userId,
 			},
-			data: { githubToken },
+			data: {
+				githubToken: req.body.githubToken,
+			},
+		});
+		resp.status(200);
+	} catch (e) {
+		console.log(e);
+		resp.status(500);
+	} finally {
+		resp.end();
+	}
+};
+
+const handleUpdateGeminiToken: express.Handler = async (req, resp) => {
+	try {
+		await db.project.update({
+			where: {
+				id: Number(req.params["projectId"]),
+				userId: resp.locals.userId,
+			},
+			data: {
+				geminiApiKey: req.body.geminiApiKey,
+			},
 		});
 		resp.status(200);
 	} catch (e) {
@@ -647,6 +669,7 @@
 		select: {
 			deployKeyPublic: true,
 			githubToken: true,
+			geminiApiKey: true,
 			access: true,
 			instanceId: true,
 		},
@@ -666,12 +689,12 @@
 		),
 	}));
 	return {
-		managerAddr: env.INTERNAL_API_ADDR,
 		deployKeyPublic: project.deployKeyPublic == null ? undefined : project.deployKeyPublic,
 		instanceId: project.instanceId == null ? undefined : project.instanceId,
 		access: JSON.parse(project.access ?? "[]"),
 		integrations: {
 			github: !!project.githubToken,
+			gemini: !!project.geminiApiKey,
 		},
 		networks: getNetworks(username),
 		services,
@@ -911,16 +934,9 @@
 };
 
 const auth = (req: express.Request, resp: express.Response, next: express.NextFunction) => {
-	const userId = req.get("x-forwarded-userid");
-	const username = req.get("x-forwarded-user");
-	if (userId == null || username == null) {
-		resp.status(401);
-		resp.write("Unauthorized");
-		resp.end();
-		return;
-	}
-	resp.locals.userId = userId;
-	resp.locals.username = username;
+	// Hardcoded user for development
+	resp.locals.userId = "1";
+	resp.locals.username = "gio";
 	next();
 };
 
@@ -1020,6 +1036,7 @@
 	projectRouter.delete("/:projectId", handleProjectDelete);
 	projectRouter.get("/:projectId/repos/github", handleGithubRepos);
 	projectRouter.post("/:projectId/github-token", handleUpdateGithubToken);
+	projectRouter.post("/:projectId/gemini-token", handleUpdateGeminiToken);
 	projectRouter.get("/:projectId/env", handleEnv);
 	projectRouter.post("/:projectId/reload/:serviceName/:workerId", handleReloadWorker);
 	projectRouter.post("/:projectId/reload", handleReload);