/workspaces refactor

This commit is contained in:
2026-02-19 16:07:00 +00:00
parent 4dde3aec66
commit 9870fa7ae8
21 changed files with 716 additions and 227 deletions
+14 -3
View File
@@ -16,6 +16,8 @@ export type TerminalViewProps = {
className?: string;
style?: CSSProperties;
wsPath?: string;
sessionId?: string;
sandboxed?: boolean;
fontSize?: number;
fontFamily?: string;
theme?: TerminalTheme;
@@ -32,17 +34,22 @@ const DEFAULT_THEME: Required<TerminalTheme> = {
selectionBackground: '#3a3a5e',
};
const buildWsUrl = (wsPath: string) => {
const buildWsUrl = (wsPath: string, sessionId?: string, sandboxed?: boolean) => {
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
const token = localStorage.getItem('BEARER_TOKEN') ?? '';
const separator = wsPath.includes('?') ? '&' : '?';
return `${protocol}//${window.location.host}${wsPath}${separator}token=${encodeURIComponent(token)}`;
let url = `${protocol}//${window.location.host}${wsPath}${separator}token=${encodeURIComponent(token)}`;
if (sessionId) url += `&sessionId=${encodeURIComponent(sessionId)}`;
if (sandboxed === false) url += '&sandboxed=false';
return url;
};
export const TerminalView = ({
className,
style,
wsPath = '/api/terminal/ws',
sessionId,
sandboxed = true,
fontSize = 14,
fontFamily = 'Menlo, Monaco, "Courier New", monospace',
theme,
@@ -99,7 +106,7 @@ export const TerminalView = ({
fitAddonRef.current = fitAddon;
onReadyRef.current?.(term);
const ws = new WebSocket(buildWsUrl(wsPath));
const ws = new WebSocket(buildWsUrl(wsPath, sessionId, sandboxed));
wsRef.current = ws;
const handleOpen = () => {
@@ -114,6 +121,8 @@ export const TerminalView = ({
} else if (msg.type === 'exit') {
term.write('\r\n[Process exited]\r\n');
onExitRef.current?.();
} else if (msg.type === 'detached') {
term.write('\r\n[Session taken over]\r\n');
}
} catch {
// ignore
@@ -169,6 +178,8 @@ export const TerminalView = ({
}, [
isMounted,
wsPath,
sessionId,
sandboxed,
fontSize,
fontFamily,
background,
+40
View File
@@ -0,0 +1,40 @@
const words = [
'amber', 'anchor', 'apple', 'arrow', 'atlas', 'autumn', 'badge', 'basin', 'beacon', 'blade',
'blaze', 'bloom', 'bolt', 'branch', 'brave', 'breeze', 'brick', 'bridge', 'brook', 'brush',
'cairn', 'canvas', 'cargo', 'cedar', 'chain', 'chalk', 'chase', 'cherry', 'cipher', 'clash',
'cliff', 'clock', 'cloud', 'clover', 'comet', 'coral', 'crane', 'creek', 'crest', 'crown',
'crystal', 'curve', 'dagger', 'dawn', 'delta', 'depth', 'desert', 'dew', 'dice', 'dome',
'dragon', 'drift', 'drum', 'dusk', 'eagle', 'echo', 'edge', 'ember', 'fable', 'falcon',
'fern', 'field', 'flame', 'flare', 'flint', 'flora', 'forge', 'fossil', 'frost', 'galaxy',
'garden', 'garnet', 'gate', 'glacier', 'glade', 'glaze', 'gleam', 'globe', 'gorge', 'grain',
'grape', 'grove', 'gust', 'harbor', 'hawk', 'hazel', 'heart', 'hedge', 'helm', 'heron',
'hive', 'hollow', 'honey', 'horizon', 'humble', 'index', 'inlet', 'iron', 'island', 'ivory',
'jade', 'jasper', 'jewel', 'jungle', 'karma', 'kelp', 'kernel', 'kettle', 'lance', 'lantern',
'latch', 'laurel', 'lava', 'leaf', 'ledge', 'lens', 'light', 'linen', 'lotus', 'lunar',
'magic', 'maple', 'marble', 'marsh', 'mason', 'meadow', 'mesa', 'metal', 'mint', 'mirror',
'mist', 'molar', 'moon', 'mortar', 'mosaic', 'moss', 'mural', 'nebula', 'nectar', 'nerve',
'night', 'noble', 'north', 'novel', 'oasis', 'olive', 'onyx', 'orbit', 'orchid', 'origin',
'otter', 'oxide', 'oyster', 'paddle', 'palm', 'panda', 'panel', 'pearl', 'pebble', 'pepper',
'phase', 'pine', 'pixel', 'plain', 'plume', 'point', 'polar', 'pond', 'prism', 'pulse',
'quartz', 'quest', 'quill', 'radar', 'rapid', 'raven', 'realm', 'reef', 'ridge', 'river',
'robin', 'rocket', 'rouge', 'route', 'ruby', 'rustic', 'sage', 'sail', 'sand', 'satin',
'scout', 'shell', 'shield', 'shore', 'sigma', 'silk', 'slate', 'slope', 'solar', 'spark',
'spear', 'spice', 'spine', 'spoke', 'spring', 'sprout', 'stamp', 'steel', 'stone', 'storm',
'stream', 'summit', 'swan', 'swift', 'talon', 'tangle', 'temple', 'terra', 'thistle', 'thorn',
'thunder', 'tide', 'tiger', 'timber', 'torch', 'tower', 'trail', 'trend', 'tropic', 'tulip',
'tunnel', 'umbra', 'valley', 'vapor', 'vault', 'velvet', 'venus', 'verge', 'vessel', 'vigor',
'vine', 'violet', 'vista', 'vivid', 'vortex', 'wander', 'wave', 'wheat', 'willow', 'wind',
'winter', 'wolf', 'zenith', 'zephyr',
];
const pick = () => words[Math.floor(Math.random() * words.length)]!;
export const generateSlug = (count = 3) => Array.from({ length: count }, pick).join('-');
export const slugify = (text: string) =>
text
.normalize('NFD')
.replace(/[\u0300-\u036f]/g, '')
.toLowerCase()
.replace(/[^a-z0-9]+/g, '-')
.replace(/^-|-$/g, '');