fix(workspace): docs discovery for doc/ dirs + SSH terminal tab args

- Add doc/ alongside docs/ in markdown file discovery (groups.rs)
- Add SETUP.md to priority root files
- Fix SSH terminal tabs: resolve session args via sshArgsCache derived
  from listSshSessions() instead of passing empty args
- Fix Agent Preview: only mount xterm when tab is active (prevents
  CanvasAddon crash on hidden elements)
- Separate tab type rendering (shell/ssh/agent-preview) with proper guards
This commit is contained in:
DexterFromLab 2026-03-11 13:04:32 +01:00
parent dc0ffb6dbf
commit 44610f3177
2 changed files with 69 additions and 19 deletions

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { onMount } from 'svelte';
import type { ProjectConfig } from '../../types/groups';
import {
getTerminalTabs,
@ -6,9 +7,33 @@
removeTerminalTab,
type TerminalTab,
} from '../../stores/workspace.svelte';
import { listSshSessions, type SshSession } from '../../adapters/ssh-bridge';
import TerminalPane from '../Terminal/TerminalPane.svelte';
import AgentPreviewPane from '../Terminal/AgentPreviewPane.svelte';
/** Cached SSH sessions for building args */
let sshSessions = $state<SshSession[]>([]);
onMount(() => {
listSshSessions().then(s => { sshSessions = s; }).catch(() => {});
});
/** Resolved SSH args per tab, keyed by tab id */
let sshArgsCache = $derived.by(() => {
const cache: Record<string, string[]> = {};
for (const tab of tabs) {
if (tab.type !== 'ssh' || !tab.sshSessionId) continue;
const session = sshSessions.find(s => s.id === tab.sshSessionId);
if (!session) continue;
const args: string[] = [];
if (session.key_file) args.push('-i', session.key_file);
if (session.port && session.port !== 22) args.push('-p', String(session.port));
args.push(`${session.username}@${session.host}`);
cache[tab.id] = args;
}
return cache;
});
interface Props {
project: ProjectConfig;
agentSessionId?: string | null;
@ -100,17 +125,23 @@
<div class="tab-content">
{#each tabs as tab (tab.id)}
<div class="tab-pane" class:visible={activeTabId === tab.id}>
{#if activeTabId === tab.id}
{#if tab.type === 'agent-preview' && tab.agentSessionId}
<div class="tab-pane" style:display={activeTabId === tab.id ? 'block' : 'none'}>
{#if tab.type === 'agent-preview' && tab.agentSessionId}
{#if activeTabId === tab.id}
<AgentPreviewPane sessionId={tab.agentSessionId} />
{:else}
<TerminalPane
cwd={project.cwd}
shell={tab.type === 'ssh' ? '/usr/bin/ssh' : undefined}
onExit={() => handleTabExit(tab.id)}
/>
{/if}
{:else if tab.type === 'ssh' && sshArgsCache[tab.id]}
<TerminalPane
cwd={project.cwd}
shell="/usr/bin/ssh"
args={sshArgsCache[tab.id]}
onExit={() => handleTabExit(tab.id)}
/>
{:else if tab.type === 'shell'}
<TerminalPane
cwd={project.cwd}
onExit={() => handleTabExit(tab.id)}
/>
{/if}
</div>
{/each}
@ -217,11 +248,6 @@
.tab-pane {
position: absolute;
inset: 0;
display: none;
}
.tab-pane.visible {
display: block;
}
.empty-terminals {