Canvas: Add VM/PROXY dev modes support

- Update ServiceSchema to discriminate between VM and PROXY dev modes
- Add DevDisabled, DevVM, DevProxy TypeScript types
- Update ServiceData type in graph.ts for new dev structure
- Update generateDodoConfig to handle both VM and PROXY modes
- Update configToGraph to properly convert dev configurations
- Maintain backward compatibility with existing dev configurations
- Update UI and introduce two new DevVM and DevProxy components
- Fetch user machine list from headscale API

Change-Id: I8f9df4ab9bd34c049fffadb748115335e8260a54
diff --git a/apps/canvas/config/src/config.ts b/apps/canvas/config/src/config.ts
index f5957d4..7fd7066 100644
--- a/apps/canvas/config/src/config.ts
+++ b/apps/canvas/config/src/config.ts
@@ -112,25 +112,35 @@
 						? n.data.preBuildCommands.split("\n").map((cmd) => ({ bin: cmd }))
 						: [],
 					dev: n.data.dev?.enabled
-						? {
-								enabled: true,
-								mode: "VM",
-								username: env.user.username,
-								codeServer:
-									n.data.dev.expose != null
-										? {
-												network: networkMap.get(n.data.dev.expose.network)!,
-												subdomain: n.data.dev.expose.subdomain,
-											}
-										: undefined,
-								ssh:
-									n.data.dev.expose != null
-										? {
-												network: networkMap.get(n.data.dev.expose.network)!,
-												subdomain: n.data.dev.expose.subdomain,
-											}
-										: undefined,
-							}
+						? n.data.dev.mode === "VM"
+							? {
+									enabled: true,
+									mode: "VM",
+									username: env.user.username,
+									codeServer:
+										n.data.dev.expose != null
+											? {
+													network: networkMap.get(n.data.dev.expose.network)!,
+													subdomain: n.data.dev.expose.subdomain,
+												}
+											: undefined,
+									ssh:
+										n.data.dev.expose != null
+											? {
+													network: networkMap.get(n.data.dev.expose.network)!,
+													subdomain: n.data.dev.expose.subdomain,
+												}
+											: undefined,
+								}
+							: {
+									enabled: true,
+									mode: "PROXY",
+									address: n.data.dev.address,
+									vpn: {
+										enabled: true,
+										username: env.user.username,
+									},
+								}
 						: {
 								enabled: false,
 							},
@@ -311,7 +321,28 @@
 							? { name: "gemini", apiKey: s.model.geminiApiKey }
 							: { name: "claude", apiKey: s.model.anthropicApiKey },
 				}),
-				// TODO(gio): dev
+				dev: s.dev?.enabled
+					? s.dev.mode === "VM"
+						? {
+								enabled: true,
+								mode: "VM",
+								expose: s.dev.ssh
+									? {
+											network: s.dev.ssh.network,
+											subdomain: s.dev.ssh.subdomain,
+										}
+									: undefined,
+								codeServerNodeId: uuidv4(), // TODO: proper node tracking
+								sshNodeId: uuidv4(), // TODO: proper node tracking
+							}
+						: {
+								enabled: true,
+								mode: "PROXY",
+								address: s.dev.address,
+							}
+					: {
+							enabled: false,
+						},
 				isChoosingPortToConnect: false,
 			},
 			// TODO(gio): generate position