feat: implement web terminal for tool instances

- Add TerminalSession backend service for docker exec subprocess management
- Add TerminalManager for WebSocket session lifecycle management
- Create WebSocket endpoint at /ws/tool-instances/{id}/terminal
- Add session cookie authentication and instance ownership verification
- Install xterm.js with fit and web-links addons
- Create TerminalComponent with xterm.js integration
- Create TerminalPage with full-screen terminal view
- Add terminal route at /instances/:id/terminal
- Add terminal button to InstanceList for running instances
- Add terminal and arrow-left icons to icon registry
- Add comprehensive terminal CSS styles (dark theme, responsive)

Quality gates: typecheck ✓, lint ✓, build ✓, Python syntax ✓
This commit is contained in:
Fusion
2026-05-19 21:11:29 +02:00
parent d6b3e8b804
commit e344e961d6
23 changed files with 1136 additions and 4 deletions
+12
View File
@@ -1,4 +1,5 @@
import { useCallback, useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import { Icon } from "./icon";
import type { ToolInstance } from "../api/sessions";
import {
@@ -18,6 +19,7 @@ interface InstanceListProps {
}
export const InstanceList = ({ projectId, repoId, toolTypes }: InstanceListProps) => {
const navigate = useNavigate();
const [instances, setInstances] = useState<ToolInstance[]>([]);
const [loading, setLoading] = useState(false);
const [showCreate, setShowCreate] = useState(false);
@@ -154,6 +156,16 @@ export const InstanceList = ({ projectId, repoId, toolTypes }: InstanceListProps
Open
</a>
)}
{instance.status === "running" && (
<button
className="secondary-button small"
onClick={() => navigate(`/instances/${instance.id}/terminal`)}
type="button"
>
<Icon name="terminal" size="sm" />
Terminal
</button>
)}
{instance.status !== "running" && (
<button
className="secondary-button small"