Files
deepseek-harness/packages/api/terminal-controller/src/client/bindings.ts
T

64 lines
2.6 KiB
TypeScript

/** Independent content-to-terminal records keep concurrent browser writes disjoint. */
import type { SessionId } from '@deepseek-ai/dsh-session/types'
import type { WebTerminalId } from '../types.ts'
const PREFIX = 'dsh.terminal.binding.v1.'
/** Saved recovery targets keyed by Session and globally unique terminal content identity. */
export class TerminalBindings {
private readonly memory = new Map<string, WebTerminalId>()
/**
* Read a saved target, retaining this window's value when storage is unavailable.
* @param sessionId - owning Session.
* @param contentId - terminal content identity, shared only by deliberate copies.
* @returns the existing Host identity, if one has been saved.
*/
get(sessionId: SessionId, contentId: string): WebTerminalId | undefined {
const key = this.key(sessionId, contentId)
const known = this.memory.get(key)
if (known !== undefined) return known
if (typeof localStorage === 'undefined') return undefined
try {
const raw = localStorage.getItem(key)
if (raw === null) return undefined
const value: unknown = JSON.parse(raw)
if (typeof value !== 'string' || !/^[\w-]{1,128}$/u.test(value)) return undefined
this.memory.set(key, value as WebTerminalId)
return value as WebTerminalId
} catch (_storageUnavailable) { return undefined }
}
/**
* Save an identity before its Host allocation begins.
* @param sessionId - owning Session.
* @param contentId - globally unique terminal content identity.
* @param id - existing or newly allocated Host identity.
*/
set(sessionId: SessionId, contentId: string, id: WebTerminalId): void {
const key = this.key(sessionId, contentId)
this.memory.set(key, id)
if (typeof localStorage === 'undefined') return
try { localStorage.setItem(key, JSON.stringify(id)) }
catch (error) { console.error('Terminal binding persistence failed:', error) }
}
/**
* Remove this content's target after its close intent has been saved.
* @param sessionId - owning Session.
* @param contentId - closing terminal content identity.
*/
delete(sessionId: SessionId, contentId: string): void {
const key = this.key(sessionId, contentId)
this.memory.delete(key)
if (typeof localStorage === 'undefined') return
try { localStorage.removeItem(key) }
catch (error) { console.error('Terminal binding cleanup failed:', error) }
}
/** Release cached values when the Client service is disposed. */
clear(): void { this.memory.clear() }
private key(sessionId: SessionId, contentId: string): string { return PREFIX + JSON.stringify([sessionId, contentId]) }
}