feat: per-session store + configurable host limits; fix divider drag runaway

- state: side-store per conversation, injected as a prop instead of a module singleton
- host: schemastery Config (read/media/list/terminal limits) resolved from cordis config
- shape: types/exports/peerDependencies for the web profile + plugin-shape spec
- fix: split divider emits incremental deltas so drags track the cursor 1:1
- docs: README refresh
This commit is contained in:
Menghuan1918
2026-08-09 22:07:03 +08:00
parent a10c9fc77e
commit e2ee427ea3
16 changed files with 421 additions and 97 deletions
+5 -5
View File
@@ -14,7 +14,7 @@ import { FitAddon } from '@xterm/addon-fit'
import 'xterm/css/xterm.css'
import { t } from './locales.ts'
import type { SessionScope } from './api.ts'
import { sidebarStore } from './state.ts'
import type { SidebarStore } from './state.ts'
import { isDarkScheme, subscribeColorScheme, tokenValue } from './theme.ts'
import css from './sidebar.module.css'
@@ -60,8 +60,8 @@ function xtermTheme(): ITheme {
}
}
export function TerminalView(props: { scope: SessionScope; tabId: string }) {
const { scope, tabId } = props
export function TerminalView(props: { scope: SessionScope; tabId: string; store: SidebarStore }) {
const { scope, tabId, store } = props
const hostRef = useRef<HTMLDivElement>(null)
const [connected, setConnected] = useState(false)
const [fatal, setFatal] = useState<string | null>(null)
@@ -180,7 +180,7 @@ export function TerminalView(props: { scope: SessionScope; tabId: string }) {
// the process to the host's reconnect grace: switching back or
// refreshing reattaches the SAME shell instead of respawning one.
// (The host respawns on its own when the authoritative cwd changed.)
if (!sidebarStore.tabOpen(scope.sessionId, tabId)
if (!store.tabOpen(scope.sessionId, tabId)
&& socket !== null && socket.readyState === WebSocket.OPEN) {
socket.send(JSON.stringify({ type: 'close' }))
}
@@ -188,7 +188,7 @@ export function TerminalView(props: { scope: SessionScope; tabId: string }) {
term.dispose()
connectRef.current = null
}
}, [scope.sessionId, scope.cwd, tabId])
}, [scope.sessionId, scope.cwd, tabId, store])
return (
<div className={css.terminalWrap}>