[Init] Initial commit - NetMesh terminal manager
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
This commit is contained in:
262
types/global/netcatty-bridge-ai.d.ts
vendored
Normal file
262
types/global/netcatty-bridge-ai.d.ts
vendored
Normal file
@@ -0,0 +1,262 @@
|
||||
import type { CodebuddyAdvancedOptions } from '../../infrastructure/ai/types';
|
||||
|
||||
declare global {
|
||||
interface NetcattyBridge {
|
||||
// AI / external agents
|
||||
aiSyncProviders?(providers: Array<{ id: string; providerId: string; apiKey?: string; baseURL?: string; enabled: boolean }>): Promise<{ ok: boolean }>;
|
||||
aiChatStream?(requestId: string, url: string, headers?: Record<string, string>, body?: string, providerId?: string, idleTimeoutMs?: number): Promise<{ ok: boolean; statusCode?: number; statusText?: string; error?: string; aborted?: boolean }>;
|
||||
aiChatCancel?(requestId: string): Promise<boolean>;
|
||||
aiFetch?(url: string, method?: string, headers?: Record<string, string>, body?: string, providerId?: string, skipHostCheck?: boolean, followRedirects?: boolean, skipTLSVerify?: boolean): Promise<{ ok: boolean; status?: number; data: string; error?: string }>;
|
||||
aiAllowlistAddHost?(baseURL: string): Promise<{ ok: boolean; error?: string }>;
|
||||
aiExec?(sessionId: string, command: string, chatSessionId?: string): Promise<{ ok: boolean; stdout?: string; stderr?: string; exitCode?: number | null; error?: string }>;
|
||||
aiCattyCancelExec?(chatSessionId: string): Promise<{ ok: boolean; error?: string }>;
|
||||
aiDiscoverAgents?(options?: { refreshShellEnv?: boolean; apiKeyPresent?: boolean }): Promise<Array<{
|
||||
command: string;
|
||||
name: string;
|
||||
icon: string;
|
||||
description: string;
|
||||
args: string[];
|
||||
path: string;
|
||||
binPath?: string;
|
||||
version: string;
|
||||
available: boolean;
|
||||
installed?: boolean;
|
||||
authenticated?: boolean;
|
||||
authSource?: string | null;
|
||||
sdkBackend?: string;
|
||||
/** @deprecated Legacy persisted field from the pre-SDK migration. */
|
||||
acpCommand?: string;
|
||||
acpArgs?: string[];
|
||||
}>>;
|
||||
aiPrewarmShellEnv?(): Promise<{ ok: boolean; error?: string }>;
|
||||
aiCodexGetIntegration?(options?: { refreshShellEnv?: boolean; validateChatGptAuth?: boolean; codexPath?: string }): Promise<{
|
||||
state: 'connected_chatgpt' | 'connected_api_key' | 'connected_custom_config' | 'not_logged_in' | 'unknown';
|
||||
isConnected: boolean;
|
||||
rawOutput: string;
|
||||
exitCode: number | null;
|
||||
customConfig?: {
|
||||
providerName: string;
|
||||
displayName: string;
|
||||
baseUrl: string | null;
|
||||
envKey: string | null;
|
||||
envKeyPresent: boolean;
|
||||
hasHardcodedApiKey: boolean;
|
||||
model: string | null;
|
||||
authHash: string | null;
|
||||
} | null;
|
||||
}>;
|
||||
aiCodexStartLogin?(options?: { codexPath?: string }): Promise<{
|
||||
ok: boolean;
|
||||
session?: {
|
||||
sessionId: string;
|
||||
state: 'running' | 'success' | 'error' | 'cancelled';
|
||||
url: string | null;
|
||||
output: string;
|
||||
error: string | null;
|
||||
exitCode: number | null;
|
||||
codexPath?: string | null;
|
||||
};
|
||||
error?: string;
|
||||
}>;
|
||||
aiCodexGetLoginSession?(sessionId: string): Promise<{
|
||||
ok: boolean;
|
||||
session?: {
|
||||
sessionId: string;
|
||||
state: 'running' | 'success' | 'error' | 'cancelled';
|
||||
url: string | null;
|
||||
output: string;
|
||||
error: string | null;
|
||||
exitCode: number | null;
|
||||
codexPath?: string | null;
|
||||
};
|
||||
error?: string;
|
||||
}>;
|
||||
aiCodexCancelLogin?(sessionId: string): Promise<{
|
||||
ok: boolean;
|
||||
found?: boolean;
|
||||
session?: {
|
||||
sessionId: string;
|
||||
state: 'running' | 'success' | 'error' | 'cancelled';
|
||||
url: string | null;
|
||||
output: string;
|
||||
error: string | null;
|
||||
exitCode: number | null;
|
||||
codexPath?: string | null;
|
||||
};
|
||||
error?: string;
|
||||
}>;
|
||||
aiCodexLogout?(options?: { codexPath?: string }): Promise<{
|
||||
ok: boolean;
|
||||
state?: 'connected_chatgpt' | 'connected_api_key' | 'connected_custom_config' | 'not_logged_in' | 'unknown';
|
||||
isConnected?: boolean;
|
||||
rawOutput?: string;
|
||||
logoutOutput?: string;
|
||||
error?: string;
|
||||
}>;
|
||||
aiMcpUpdateSessions?(sessions: Array<{
|
||||
sessionId: string;
|
||||
hostId?: string;
|
||||
hostname: string;
|
||||
label: string;
|
||||
os?: string;
|
||||
username?: string;
|
||||
protocol?: string;
|
||||
shellType?: string;
|
||||
deviceType?: string;
|
||||
connected: boolean;
|
||||
hostChain?: Array<{ hostId: string; label?: string; hostname?: string }>;
|
||||
activePortForwards?: Array<{ ruleId: string; label?: string; type?: string; localPort?: number; status?: string }>;
|
||||
}>, chatSessionId?: string): Promise<{ ok: boolean }>;
|
||||
/** Update the app-owned live session snapshot used by existing AI scopes. */
|
||||
aiMcpUpdateLiveSessions?(sessions: Array<{
|
||||
sessionId: string;
|
||||
hostId?: string;
|
||||
hostname: string;
|
||||
label: string;
|
||||
os?: string;
|
||||
username?: string;
|
||||
protocol?: string;
|
||||
shellType?: string;
|
||||
deviceType?: string;
|
||||
connected: boolean;
|
||||
hostChain?: Array<{ hostId: string; label?: string; hostname?: string }>;
|
||||
activePortForwards?: Array<{ ruleId: string; label?: string; type?: string; localPort?: number; status?: string }>;
|
||||
}>): Promise<{ ok: boolean; count?: number; error?: string }>;
|
||||
/** Merge sessions into a chat scope without dropping existing entries. */
|
||||
aiMcpMergeSessions?(sessions: Array<{
|
||||
sessionId: string;
|
||||
hostId?: string;
|
||||
hostname: string;
|
||||
label: string;
|
||||
os?: string;
|
||||
username?: string;
|
||||
protocol?: string;
|
||||
shellType?: string;
|
||||
deviceType?: string;
|
||||
connected: boolean;
|
||||
hostChain?: Array<{ hostId: string; label?: string; hostname?: string }>;
|
||||
activePortForwards?: Array<{ ruleId: string; label?: string; type?: string; localPort?: number; status?: string }>;
|
||||
}>, chatSessionId: string): Promise<{ ok: boolean; count?: number; error?: string }>;
|
||||
onVaultAgentRequest?(cb: (payload: { requestId: string; op: string; params: Record<string, unknown> }) => void): () => void;
|
||||
respondVaultAgent?(requestId: string, result: Record<string, unknown>): Promise<{ ok: boolean; error?: string }>;
|
||||
aiMcpSetToolIntegrationMode?(mode: 'mcp' | 'skills'): Promise<{ ok: boolean; error?: string }>;
|
||||
aiUserSkillsGetStatus?(): Promise<{
|
||||
ok: boolean;
|
||||
directoryPath?: string;
|
||||
readyCount?: number;
|
||||
warningCount?: number;
|
||||
skills?: Array<{
|
||||
id: string;
|
||||
slug: string;
|
||||
directoryName: string;
|
||||
directoryPath: string;
|
||||
skillPath: string;
|
||||
name: string;
|
||||
description: string;
|
||||
status: 'ready' | 'warning';
|
||||
warnings: string[];
|
||||
}>;
|
||||
warnings?: string[];
|
||||
error?: string;
|
||||
}>;
|
||||
aiUserSkillsOpenFolder?(): Promise<{
|
||||
ok: boolean;
|
||||
directoryPath?: string;
|
||||
readyCount?: number;
|
||||
warningCount?: number;
|
||||
skills?: Array<{
|
||||
id: string;
|
||||
slug: string;
|
||||
directoryName: string;
|
||||
directoryPath: string;
|
||||
skillPath: string;
|
||||
name: string;
|
||||
description: string;
|
||||
status: 'ready' | 'warning';
|
||||
warnings: string[];
|
||||
}>;
|
||||
warnings?: string[];
|
||||
error?: string;
|
||||
}>;
|
||||
aiUserSkillsBuildContext?(prompt: string, selectedSkillSlugs?: string[]): Promise<{
|
||||
ok: boolean;
|
||||
context?: string;
|
||||
error?: string;
|
||||
}>;
|
||||
aiSkillsCliGetInvocation?(): Promise<{
|
||||
ok: boolean;
|
||||
skillPath?: string | null;
|
||||
commandPrefix?: string;
|
||||
launcherPath?: string | null;
|
||||
usesLauncher?: boolean;
|
||||
error?: string;
|
||||
}>;
|
||||
aiSdkAgentStream?(requestId: string, chatSessionId: string, sdkBackend: string, prompt: string, cwd?: string, providerId?: string, model?: string, existingSessionId?: string, historyMessages?: Array<{ role: 'user' | 'assistant'; content: string }>, images?: Array<{ base64Data: string; mediaType: string; filename?: string; filePath?: string }>, toolIntegrationMode?: 'mcp' | 'skills', defaultTargetSession?: { sessionId: string; hostname: string; label: string; os?: string; username?: string; protocol?: string; shellType?: string; deviceType?: string; connected: boolean; source: 'scope-target' | 'only-connected-in-scope' }, userSkillsContext?: string, agentEnv?: Record<string, string>, agentCommand?: string, codexRuntime?: 'sdk' | 'app-server', permissionMode?: 'observer' | 'confirm' | 'auto', codebuddyOptions?: CodebuddyAdvancedOptions): Promise<{ ok: boolean; error?: string }>;
|
||||
aiSdkAgentSteer?(requestId: string, chatSessionId: string, prompt: string, images: Array<{ base64Data: string; mediaType: string; filename?: string; filePath?: string }> | undefined, clientUserMessageId: string): Promise<{
|
||||
status: 'accepted' | 'not-steerable' | 'busy' | 'inactive' | 'unsupported' | 'cancelled' | 'failed';
|
||||
message?: string;
|
||||
turnKind?: 'review' | 'compact';
|
||||
}>;
|
||||
aiSdkAgentListModels?(sdkBackend: string, cwd?: string, providerId?: string, chatSessionId?: string, agentEnv?: Record<string, string>, agentCommand?: string, codexRuntime?: 'sdk' | 'app-server'): Promise<{ ok: boolean; models?: Array<{ id: string; name: string; description?: string; thinkingLevels?: string[]; defaultThinkingLevel?: string }>; currentModelId?: string | null; warning?: string; error?: string }>;
|
||||
codexAppServerGetStatus?(agentCommand?: string, agentEnv?: Record<string, string>): Promise<{ ok: boolean; available: boolean; error?: string }>;
|
||||
onCodexAppServerInteractionRequest?(cb: (payload: Record<string, unknown>) => void): () => void;
|
||||
onCodexAppServerInteractionCleared?(cb: (payload: { interactionIds: string[]; chatSessionId?: string }) => void): () => void;
|
||||
respondCodexAppServerInteraction?(payload: Record<string, unknown>): Promise<{ ok: boolean; error?: string }>;
|
||||
cancelCodexAppServerInteractionTimeout?(interactionId: string): Promise<{ ok: boolean; cancelled?: boolean; error?: string }>;
|
||||
aiCattyCancelExec?(chatSessionId: string): Promise<unknown>;
|
||||
aiSetChatSessionCancelled?(chatSessionId: string, cancelled?: boolean): Promise<{ ok: boolean; error?: string }>;
|
||||
aiMcpSyncPermissionGrants?(grants: Array<Record<string, unknown>>): Promise<{ ok: boolean; count?: number; error?: string }>;
|
||||
externalMcpGetStatus?(): Promise<{
|
||||
ok: boolean;
|
||||
enabled?: boolean;
|
||||
state?: string;
|
||||
host?: string;
|
||||
port?: number | null;
|
||||
discoveryPath?: string | null;
|
||||
launcherPath?: string | null;
|
||||
chatSessionId?: string;
|
||||
exposedSessionCount?: number;
|
||||
mode?: 'temporary' | 'persistent';
|
||||
idleTimeoutMinutes?: number;
|
||||
sessionIdleTimeoutMinutes?: number;
|
||||
lastActivityAt?: number | null;
|
||||
idleExpiresAt?: number | null;
|
||||
permissionMode?: string;
|
||||
hostRunning?: boolean;
|
||||
error?: string | null;
|
||||
}>;
|
||||
externalMcpSetEnabled?(enabled: boolean): Promise<Record<string, unknown>>;
|
||||
externalMcpSetConfig?(config: {
|
||||
mode?: 'temporary' | 'persistent';
|
||||
idleTimeoutMinutes?: number;
|
||||
sessionIdleTimeoutMinutes?: number;
|
||||
}): Promise<Record<string, unknown>>;
|
||||
externalMcpCodexGetStatus?(): Promise<Record<string, unknown>>;
|
||||
externalMcpCodexAdd?(): Promise<Record<string, unknown>>;
|
||||
externalMcpClaudeGetStatus?(): Promise<Record<string, unknown>>;
|
||||
externalMcpClaudeAdd?(): Promise<Record<string, unknown>>;
|
||||
externalMcpGrokGetStatus?(): Promise<Record<string, unknown>>;
|
||||
externalMcpGrokAdd?(): Promise<Record<string, unknown>>;
|
||||
aiSdkAgentCancel?(requestId: string, chatSessionId?: string): Promise<{ ok: boolean; error?: string }>;
|
||||
aiSdkAgentCleanup?(chatSessionId: string): Promise<{ ok: boolean }>;
|
||||
aiSdkAgentElicitationResponse?(elicitationId: string, action: string, content?: Record<string, unknown>): Promise<{ ok: boolean; error?: string }>;
|
||||
aiSdkAgentMcpStatus?(agentEnv?: Record<string, string>, agentCommand?: string): Promise<{ ok: boolean; servers?: Array<Record<string, unknown>>; error?: string }>;
|
||||
aiSdkAgentAccountInfo?(agentEnv?: Record<string, string>, agentCommand?: string): Promise<{ ok: boolean; account?: Record<string, unknown> | null; error?: string }>;
|
||||
aiSdkAgentPluginInstall?(options: { name: string; marketplace: string }): Promise<{ ok: boolean; result?: { success: boolean; message: string }; error?: string }>;
|
||||
aiSdkAgentPluginEnable?(name: string, marketplace: string): Promise<{ ok: boolean; result?: { success: boolean; message: string }; error?: string }>;
|
||||
aiSdkAgentPluginDisable?(name: string, marketplace: string): Promise<{ ok: boolean; result?: { success: boolean; message: string }; error?: string }>;
|
||||
aiSdkAgentMarketplaceInstall?(options: { name: string; repo: string; autoUpdate?: boolean }): Promise<{ ok: boolean; result?: { success: boolean; message: string }; error?: string }>;
|
||||
aiSdkAgentMarketplaceRemove?(options: { name: string; removePlugins?: boolean }): Promise<{ ok: boolean; result?: { success: boolean; message: string }; error?: string }>;
|
||||
onAiSdkAgentEvent?(requestId: string, cb: (event: Record<string, unknown>) => void): () => void;
|
||||
onAiSdkAgentDone?(requestId: string, cb: () => void): () => void;
|
||||
onAiSdkAgentError?(requestId: string, cb: (error: string) => void): () => void;
|
||||
onAiStreamData?(requestId: string, cb: (data: string) => void): () => void;
|
||||
onAiStreamEnd?(requestId: string, cb: () => void): () => void;
|
||||
onAiStreamError?(requestId: string, cb: (error: string) => void): () => void;
|
||||
onAiAgentStdout?(agentId: string, cb: (data: string) => void): () => void;
|
||||
onAiAgentStderr?(agentId: string, cb: (data: string) => void): () => void;
|
||||
onAiAgentExit?(agentId: string, cb: (code: number | null) => void): () => void;
|
||||
}
|
||||
}
|
||||
|
||||
export {};
|
||||
131
types/global/netcatty-bridge-app.d.ts
vendored
Normal file
131
types/global/netcatty-bridge-app.d.ts
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
|
||||
declare global {
|
||||
interface NetcattyBridge {
|
||||
// Auto-update
|
||||
checkForUpdate?(): Promise<{
|
||||
available: boolean;
|
||||
supported?: boolean;
|
||||
checking?: boolean;
|
||||
version?: string;
|
||||
releaseNotes?: string;
|
||||
releaseDate?: string | null;
|
||||
error?: string;
|
||||
}>;
|
||||
downloadUpdate?(): Promise<{ success: boolean; error?: string }>;
|
||||
installUpdate?(): void;
|
||||
getUpdateStatus?(): Promise<{ status: 'idle' | 'available' | 'downloading' | 'ready' | 'error'; percent: number; error: string | null; version: string | null; isChecking?: boolean }>;
|
||||
|
||||
onUpdateDownloadProgress?(cb: (progress: {
|
||||
percent: number;
|
||||
bytesPerSecond: number;
|
||||
transferred: number;
|
||||
total: number;
|
||||
}) => void): () => void;
|
||||
onUpdateAvailable?(cb: (info: {
|
||||
version: string;
|
||||
releaseNotes: string;
|
||||
releaseDate: string | null;
|
||||
}) => void): () => void;
|
||||
onUpdateNotAvailable?(cb: () => void): () => void;
|
||||
onUpdateDownloaded?(cb: () => void): () => void;
|
||||
onUpdateError?(cb: (payload: { error: string }) => void): () => void;
|
||||
// Fired when an install was requested but blocked by unsaved editors (#1215).
|
||||
onUpdateNeedsSave?(cb: () => void): () => void;
|
||||
onSshDeepLink?(cb: (payload: { url?: string }) => void): () => void;
|
||||
onTelnetDeepLink?(cb: (payload: { url?: string }) => void): () => void;
|
||||
onOpenTerminalPath?(cb: (payload: { path?: string }) => void): () => void;
|
||||
/** Fired once after cold-start deep-link / open-terminal queues have been drained. */
|
||||
onColdStartIntentsSettled?(cb: () => void): () => void;
|
||||
setSshDeepLinkEnabled?(enabled: boolean): Promise<boolean | { success: boolean; enabled: boolean }>;
|
||||
getSshDeepLinkEnabled?(): Promise<boolean>;
|
||||
onJmsDeepLink?(cb: (payload: { url?: string }) => void): () => void;
|
||||
setJmsDeepLinkEnabled?(enabled: boolean): Promise<boolean | { success: boolean; enabled: boolean }>;
|
||||
getJmsDeepLinkEnabled?(): Promise<boolean>;
|
||||
setExplorerContextMenuEnabled?(enabled: boolean): Promise<boolean | { success: boolean; enabled: boolean; supported?: boolean }>;
|
||||
getExplorerContextMenuEnabled?(): Promise<boolean | { enabled: boolean; supported?: boolean }>;
|
||||
|
||||
// Global Toggle Hotkey (Quake Mode)
|
||||
registerGlobalHotkey?(hotkey: string): Promise<{ success: boolean; enabled?: boolean; error?: string; accelerator?: string }>;
|
||||
unregisterGlobalHotkey?(): Promise<{ success: boolean }>;
|
||||
getGlobalHotkeyStatus?(): Promise<{ enabled: boolean; hotkey: string | null }>;
|
||||
|
||||
// Auto-Update toggle
|
||||
getAutoUpdate?(): Promise<{ enabled: boolean }>;
|
||||
setAutoUpdate?(enabled: boolean): Promise<{ success: boolean }>;
|
||||
|
||||
// SSH diagnostic logs
|
||||
getSshDebugLogInfo?(): Promise<{
|
||||
enabled: boolean;
|
||||
path: string;
|
||||
exists: boolean;
|
||||
size: number;
|
||||
}>;
|
||||
openSshDebugLogDir?(): Promise<{ success: boolean; error?: string }>;
|
||||
|
||||
// System Tray / Close to Tray
|
||||
setCloseToTray?(enabled: boolean): Promise<{ success: boolean; enabled: boolean }>;
|
||||
isCloseToTray?(): Promise<{ enabled: boolean }>;
|
||||
|
||||
// Auto Launch at system login (hidden to tray)
|
||||
getAutoLaunch?(): Promise<{ success: boolean; enabled: boolean; supported: boolean }>;
|
||||
setAutoLaunch?(enabled: boolean): Promise<{ success: boolean; enabled: boolean; supported: boolean }>;
|
||||
|
||||
// App-level HTTP(S) network proxy (cloud sync / AI — not SSH ProxyJump)
|
||||
setHttpNetworkProxy?(settings: {
|
||||
mode: 'system' | 'direct' | 'custom';
|
||||
url: string;
|
||||
bypass: string;
|
||||
}): Promise<{
|
||||
success: boolean;
|
||||
settings: { mode: 'system' | 'direct' | 'custom'; url: string; bypass: string };
|
||||
electronConfig?: unknown;
|
||||
}>;
|
||||
getHttpNetworkProxy?(): Promise<{
|
||||
settings: { mode: 'system' | 'direct' | 'custom'; url: string; bypass: string };
|
||||
}>;
|
||||
updateTrayMenuData?(data: {
|
||||
sessions?: Array<{ id: string; label: string; hostLabel: string; status: "connecting" | "connected" | "disconnected"; workspaceId?: string; workspaceTitle?: string }>;
|
||||
hosts?: Array<{ id: string; label?: string; hostname?: string; group?: string; pinned?: boolean; lastConnectedAt?: number; protocol?: string }>;
|
||||
portForwardRules?: Array<{
|
||||
id: string;
|
||||
label: string;
|
||||
type: "local" | "remote" | "dynamic";
|
||||
localPort: number;
|
||||
remoteHost?: string;
|
||||
remotePort?: number;
|
||||
status: "inactive" | "connecting" | "active" | "error";
|
||||
}>;
|
||||
}): Promise<{ success: boolean }>;
|
||||
onTrayFocusSession?(callback: (sessionId: string) => void): () => void;
|
||||
onTrayTogglePortForward?(callback: (ruleId: string, start: boolean) => void): () => void;
|
||||
|
||||
onTrayPanelJumpToSession?(callback: (sessionId: string) => void): () => void;
|
||||
onTrayPanelConnectToHost?(callback: (hostId: string) => void): () => void;
|
||||
onTrayPanelCloseSession?(callback: (sessionId: string) => void): () => void;
|
||||
|
||||
hideTrayPanel?(): Promise<{ success: boolean }>;
|
||||
openMainWindow?(): Promise<{ success: boolean }>;
|
||||
quitApp?(): Promise<{ success: boolean }>;
|
||||
jumpToSessionFromTrayPanel?(sessionId: string): Promise<{ success: boolean }>;
|
||||
connectToHostFromTrayPanel?(hostId: string): Promise<{ success: boolean }>;
|
||||
closeSessionFromTrayPanel?(sessionId: string): Promise<{ success: boolean }>;
|
||||
onTrayPanelCloseRequest?(callback: () => void): () => void;
|
||||
onTrayPanelRefresh?(callback: () => void): () => void;
|
||||
onTrayPanelMenuData?(callback: (data: {
|
||||
sessions?: Array<{ id: string; label: string; hostLabel: string; status: "connecting" | "connected" | "disconnected"; workspaceId?: string; workspaceTitle?: string }>;
|
||||
hosts?: Array<{ id: string; label?: string; hostname?: string; group?: string; pinned?: boolean; lastConnectedAt?: number; protocol?: string }>;
|
||||
portForwardRules?: Array<{
|
||||
id: string;
|
||||
label: string;
|
||||
type: "local" | "remote" | "dynamic";
|
||||
localPort: number;
|
||||
remoteHost?: string;
|
||||
remotePort?: number;
|
||||
status: "inactive" | "connecting" | "active" | "error";
|
||||
hostId?: string;
|
||||
}>;
|
||||
}) => void): () => void;
|
||||
}
|
||||
}
|
||||
|
||||
export {};
|
||||
152
types/global/netcatty-bridge-files.d.ts
vendored
Normal file
152
types/global/netcatty-bridge-files.d.ts
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
import type { SftpFilenameEncoding } from "../../types";
|
||||
|
||||
declare global {
|
||||
interface NetcattyBridge {
|
||||
// File opener helpers (for "Open With" feature)
|
||||
selectApplication?(): Promise<{ path: string; name: string } | null>;
|
||||
openWithApplication?(filePath: string, appPath: string): Promise<boolean>;
|
||||
openWithSystemDefault?(filePath: string): Promise<{ success: boolean; error?: string }>;
|
||||
downloadSftpToTempWithProgress?(
|
||||
sftpId: string,
|
||||
remotePath: string,
|
||||
fileName: string,
|
||||
encoding: SftpFilenameEncoding | undefined,
|
||||
transferId: string
|
||||
): Promise<{ localPath: string; cancelled: boolean }>;
|
||||
|
||||
// Save dialog for file downloads
|
||||
showSaveDialog?(defaultPath: string, filters?: Array<{ name: string; extensions: string[] }>): Promise<string | null>;
|
||||
selectDirectory?(title?: string, defaultPath?: string): Promise<string | null>;
|
||||
selectFile?(title?: string, defaultPath?: string, filters?: Array<{ name: string; extensions: string[] }>): Promise<string | null>;
|
||||
|
||||
// File watcher for auto-sync feature
|
||||
startFileWatch?(localPath: string, remotePath: string, sftpId: string, encoding?: SftpFilenameEncoding): Promise<{ watchId: string }>;
|
||||
stopFileWatch?(watchId: string, cleanupTempFile?: boolean): Promise<{ success: boolean }>;
|
||||
listFileWatches?(): Promise<Array<{ watchId: string; localPath: string; remotePath: string; sftpId: string }>>;
|
||||
registerTempFile?(sftpId: string, localPath: string): Promise<{ success: boolean }>;
|
||||
unregisterTempFile?(sftpId: string, localPath: string): Promise<{ success: boolean; retained?: boolean }>;
|
||||
onFileWatchSynced?(cb: (payload: { watchId: string; localPath: string; remotePath: string; bytesWritten: number }) => void): () => void;
|
||||
onFileWatchError?(cb: (payload: { watchId: string; localPath: string; remotePath: string; error: string }) => void): () => void;
|
||||
onFileWatchStopped?(cb: (payload: { watchId: string; localPath: string; remotePath: string; sftpId: string }) => void): () => void;
|
||||
|
||||
// Temp file cleanup
|
||||
deleteTempFile?(filePath: string): Promise<{ success: boolean }>;
|
||||
stageUploadFile?(file: File, transferId: string): Promise<string>;
|
||||
cancelStagedUploadFile?(transferId: string): Promise<{ success: boolean }>;
|
||||
|
||||
// Crash Logs
|
||||
getCrashLogs?(): Promise<Array<{ fileName: string; date: string; size: number; entryCount: number }>>;
|
||||
readCrashLog?(fileName: string): Promise<Array<{
|
||||
timestamp: string;
|
||||
source: string;
|
||||
message: string;
|
||||
stack?: string;
|
||||
errorMeta?: Record<string, unknown>;
|
||||
extra?: Record<string, unknown>;
|
||||
pid?: number;
|
||||
platform?: string;
|
||||
arch?: string;
|
||||
version?: string;
|
||||
electronVersion?: string;
|
||||
osVersion?: string;
|
||||
memoryMB?: { rss: number; heapUsed: number; heapTotal: number };
|
||||
activeSessionCount?: number;
|
||||
uptimeSeconds?: number;
|
||||
}>>;
|
||||
clearCrashLogs?(): Promise<{ deletedCount: number }>;
|
||||
openCrashLogsDir?(): Promise<{ success: boolean }>;
|
||||
|
||||
// Temp directory management
|
||||
getTempDirInfo?(): Promise<{ path: string; fileCount: number; totalSize: number }>;
|
||||
clearTempDir?(): Promise<{ deletedCount: number; failedCount: number; error?: string }>;
|
||||
getTempDirPath?(): Promise<string>;
|
||||
openTempDir?(): Promise<{ success: boolean }>;
|
||||
getToolOutputPersistenceStatus?(): Promise<{ durable: boolean; reason?: string }>;
|
||||
writeToolOutputTemp?(record: import('../../infrastructure/ai/harness/toolOutputStore').PersistedToolOutputRecord, content: string): Promise<{ ok: boolean; path?: string; manifestPath?: string; error?: string }>;
|
||||
restoreToolOutputTemp?(handleId: string, chatSessionId: string): Promise<{
|
||||
path: string;
|
||||
record: import('../../infrastructure/ai/harness/toolOutputStore').PersistedToolOutputRecord;
|
||||
} | null>;
|
||||
readToolOutputTemp?(filePath: string, request?: {
|
||||
mode?: 'head' | 'tail' | 'full' | 'range' | 'search';
|
||||
maxChars?: number;
|
||||
offset?: number;
|
||||
query?: string;
|
||||
}): Promise<unknown | null>;
|
||||
deleteToolOutputTemp?(filePath: string): Promise<{ ok: boolean }>;
|
||||
deleteChatToolOutputsTemp?(chatSessionId: string): Promise<{ deletedCount: number }>;
|
||||
deleteTerminalToolOutputsTemp?(chatSessionId: string, terminalSessionId: string): Promise<{ deletedCount: number }>;
|
||||
deleteTerminalToolOutputsEverywhereTemp?(terminalSessionId: string): Promise<{ deletedCount: number }>;
|
||||
|
||||
// Session Logs
|
||||
exportSessionLog?(payload: {
|
||||
terminalData: string;
|
||||
hostLabel: string;
|
||||
hostname: string;
|
||||
startTime: number;
|
||||
format: 'txt' | 'raw' | 'html';
|
||||
}): Promise<{ success: boolean; canceled?: boolean; filePath?: string }>;
|
||||
selectSessionLogsDir?(): Promise<{ success: boolean; canceled?: boolean; directory?: string }>;
|
||||
autoSaveSessionLog?(payload: {
|
||||
terminalData: string;
|
||||
hostLabel: string;
|
||||
hostname: string;
|
||||
hostId: string;
|
||||
startTime: number;
|
||||
format: 'txt' | 'raw' | 'html';
|
||||
directory: string;
|
||||
}): Promise<{ success: boolean; error?: string; filePath?: string }>;
|
||||
openSessionLogsDir?(directory: string): Promise<{ success: boolean; error?: string }>;
|
||||
clearSessionLogsDir?(directory: string): Promise<{ success: boolean; deletedCount: number; failedCount: number; error?: string }>;
|
||||
chooseManualSessionLogPath?(payload: {
|
||||
sessionId: string;
|
||||
sessionName?: string;
|
||||
preferredDirectory?: string;
|
||||
format?: 'txt' | 'raw' | 'html';
|
||||
}): Promise<{
|
||||
success: boolean;
|
||||
canceled?: boolean;
|
||||
error?: string;
|
||||
selectionToken?: string;
|
||||
filePath?: string;
|
||||
format?: 'txt' | 'raw' | 'html';
|
||||
}>;
|
||||
startManualSessionLog?(payload: {
|
||||
sessionId: string;
|
||||
sessionName?: string;
|
||||
preferredDirectory?: string;
|
||||
/** Opaque token from chooseManualSessionLogPath (path is main-process only). */
|
||||
selectionToken?: string;
|
||||
format?: 'txt' | 'raw' | 'html';
|
||||
timestampsEnabled?: boolean;
|
||||
initialLine?: string;
|
||||
alternateScreenActive?: boolean;
|
||||
}): Promise<{ success: boolean; started: boolean; canceled?: boolean; error?: string; filePath?: string }>;
|
||||
stopManualSessionLog?(payload: {
|
||||
sessionId: string;
|
||||
}): Promise<{ success: boolean; stopped: boolean; error?: string; filePath?: string }>;
|
||||
getManualSessionLogStatus?(payload: {
|
||||
sessionId: string;
|
||||
}): Promise<{ success: boolean; isLogging: boolean; error?: string }>;
|
||||
|
||||
// Get file path from File object (for drag-and-drop, uses Electron's webUtils)
|
||||
getPathForFile?(file: File): string | undefined;
|
||||
showSystemNotification?(payload: {
|
||||
title: string;
|
||||
body: string;
|
||||
sessionId?: string;
|
||||
}): Promise<{ shown: boolean; reason?: string }>;
|
||||
readClipboardText?(): Promise<string>;
|
||||
writeClipboardText?(text: string): Promise<boolean>;
|
||||
readClipboardFiles?(): Promise<Array<{ path: string; name: string; isDirectory: boolean; size?: number }>>;
|
||||
readClipboardImage?(): Promise<{ path: string; name: string; mediaType: string; size?: number } | null>;
|
||||
hasClipboardImage?(): Promise<boolean>;
|
||||
|
||||
// Credential encryption (field-level safeStorage for sensitive data at rest)
|
||||
credentialsAvailable?(): Promise<boolean>;
|
||||
credentialsEncrypt?(plaintext: string): Promise<string>;
|
||||
credentialsDecrypt?(value: string): Promise<string>;
|
||||
}
|
||||
}
|
||||
|
||||
export {};
|
||||
172
types/global/netcatty-bridge-script.d.ts
vendored
Normal file
172
types/global/netcatty-bridge-script.d.ts
vendored
Normal file
@@ -0,0 +1,172 @@
|
||||
/// <reference path="./netcatty-bridge-script.d.ts" />
|
||||
|
||||
export type ScriptRunStatus = 'running' | 'paused' | 'completed' | 'failed';
|
||||
|
||||
export type ScriptProgressMode = 'activity' | 'determinate';
|
||||
|
||||
export interface ScriptRunLogEntry {
|
||||
at: number;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export interface ScriptRun {
|
||||
runId: string;
|
||||
scriptId?: string;
|
||||
scriptLabel?: string;
|
||||
sessionId: string;
|
||||
status: ScriptRunStatus;
|
||||
startedAt: number;
|
||||
endedAt?: number;
|
||||
/** @deprecated Use activityLabel for UI; kept for backward compatibility */
|
||||
currentStep?: string;
|
||||
stepIndex?: number;
|
||||
/** Internal telemetry only; do not use for overlay percentage */
|
||||
totalSteps?: number;
|
||||
progressMode?: ScriptProgressMode;
|
||||
activityLabel?: string;
|
||||
progressLabel?: string;
|
||||
progressCurrent?: number;
|
||||
progressTotal?: number;
|
||||
elapsedMs?: number;
|
||||
waitingFor?: string;
|
||||
logs: ScriptRunLogEntry[];
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export interface ScriptScreenSnapshot {
|
||||
rows: number;
|
||||
cols: number;
|
||||
currentRow: number;
|
||||
lines: string[];
|
||||
}
|
||||
|
||||
export interface ScriptDialogOption {
|
||||
label: string;
|
||||
value: string;
|
||||
description?: string;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
export type ScriptDialogConditionValue = string | number | boolean;
|
||||
|
||||
export type ScriptDialogCondition =
|
||||
| { field: string; equals: ScriptDialogConditionValue }
|
||||
| { field: string; notEquals: ScriptDialogConditionValue }
|
||||
| { field: string; truthy: true }
|
||||
| { field: string; falsy: true };
|
||||
|
||||
export interface ScriptDialogFieldBase {
|
||||
name: string;
|
||||
label: string;
|
||||
description?: string;
|
||||
required?: boolean;
|
||||
visibleWhen?: ScriptDialogCondition;
|
||||
}
|
||||
|
||||
export interface ScriptDialogChoiceField extends ScriptDialogFieldBase {
|
||||
type: 'select' | 'radio';
|
||||
options: ScriptDialogOption[];
|
||||
defaultValue: string;
|
||||
}
|
||||
|
||||
export interface ScriptDialogCheckboxField extends ScriptDialogFieldBase {
|
||||
type: 'checkbox';
|
||||
defaultValue: boolean;
|
||||
}
|
||||
|
||||
export interface ScriptDialogTextareaField extends ScriptDialogFieldBase {
|
||||
type: 'textarea';
|
||||
defaultValue: string;
|
||||
placeholder?: string;
|
||||
}
|
||||
|
||||
export interface ScriptDialogNumberField extends ScriptDialogFieldBase {
|
||||
type: 'number';
|
||||
defaultValue?: number;
|
||||
placeholder?: string;
|
||||
min?: number;
|
||||
max?: number;
|
||||
step?: number;
|
||||
}
|
||||
|
||||
export type ScriptDialogField =
|
||||
| ScriptDialogChoiceField
|
||||
| ScriptDialogCheckboxField
|
||||
| ScriptDialogTextareaField
|
||||
| ScriptDialogNumberField;
|
||||
|
||||
export interface ScriptDialogForm {
|
||||
title?: string;
|
||||
message: string;
|
||||
submitLabel?: string;
|
||||
cancelLabel?: string;
|
||||
fields: ScriptDialogField[];
|
||||
}
|
||||
|
||||
export type ScriptDialogFormValue = string | boolean | number | undefined;
|
||||
|
||||
export interface ScriptDialogRequest {
|
||||
requestId: string;
|
||||
type: 'alert' | 'confirm' | 'prompt' | 'waitForTimeout' | 'form';
|
||||
message: string;
|
||||
defaultValue?: string;
|
||||
sensitive?: boolean;
|
||||
pattern?: string;
|
||||
timeoutMs?: number;
|
||||
form?: ScriptDialogForm;
|
||||
}
|
||||
|
||||
export interface ScriptRunParams {
|
||||
/** Optional caller-generated id so a queued run can be cancelled before it starts. */
|
||||
runId?: string;
|
||||
/** Return after the run enters the backend queue instead of waiting for completion. */
|
||||
returnWhenQueued?: boolean;
|
||||
scriptId?: string;
|
||||
scriptLabel?: string;
|
||||
content: string;
|
||||
sessionId?: string;
|
||||
sessionIds?: string[];
|
||||
mode?: 'sequential' | 'parallel';
|
||||
permissionMode?: 'observer' | 'confirm' | 'auto';
|
||||
/** Renderer-provided session state (worker SSH sessions are not in main-process map). */
|
||||
sessionMeta?: {
|
||||
connected?: boolean;
|
||||
name?: string;
|
||||
hostname?: string;
|
||||
username?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export type ScriptRecordingStep =
|
||||
| { type: 'send'; value: string; sensitive?: boolean }
|
||||
| { type: 'waitFor'; value: string; timeoutMs?: number }
|
||||
| { type: 'waitForPrompt'; timeoutMs?: number }
|
||||
| { type: 'sleep'; value: number };
|
||||
|
||||
declare global {
|
||||
interface NetcattyBridge {
|
||||
scriptRun(params: ScriptRunParams): Promise<{ runId: string; runIds: string[] }>;
|
||||
scriptStop(runId: string): Promise<{ ok: boolean }>;
|
||||
scriptPause(runId: string): Promise<{ ok: boolean }>;
|
||||
scriptResume(runId: string): Promise<{ ok: boolean }>;
|
||||
scriptGetRuns(sessionId?: string): Promise<ScriptRun[]>;
|
||||
scriptDialogResponse(requestId: string, value?: unknown, cancelled?: boolean): Promise<{ ok: boolean }>;
|
||||
scriptScreenSnapshotResponse(requestId: string, snapshot: ScriptScreenSnapshot): Promise<{ ok: boolean }>;
|
||||
scriptRecordingStart(sessionId: string): Promise<{ ok: boolean }>;
|
||||
scriptRecordingStop(sessionId: string): Promise<{ steps: ScriptRecordingStep[]; code: string }>;
|
||||
scriptRecordingAppendStep(sessionId: string, step: ScriptRecordingStep): Promise<{
|
||||
ok: boolean;
|
||||
stopped?: boolean;
|
||||
reason?: 'limit';
|
||||
error?: string;
|
||||
steps?: ScriptRecordingStep[];
|
||||
code?: string;
|
||||
}>;
|
||||
onScriptRunsUpdated(cb: (payload: { runs: ScriptRun[] }) => void): () => void;
|
||||
onScriptDialogRequest(cb: (payload: ScriptDialogRequest) => void): () => void;
|
||||
onScriptScreenSnapshotRequest(cb: (payload: { requestId: string; sessionId: string }) => void): () => void;
|
||||
onScriptSessionInput(cb: (payload: { sessionId: string; data: string }) => void): () => void;
|
||||
}
|
||||
}
|
||||
|
||||
export {};
|
||||
620
types/global/netcatty-bridge-session.d.ts
vendored
Normal file
620
types/global/netcatty-bridge-session.d.ts
vendored
Normal file
@@ -0,0 +1,620 @@
|
||||
|
||||
declare global {
|
||||
interface NetcattyKittyKeyboardModeState {
|
||||
mainFlags: number;
|
||||
alternateFlags: number;
|
||||
mainStack: number[];
|
||||
alternateStack: number[];
|
||||
alternateScreenActive: boolean;
|
||||
}
|
||||
|
||||
interface NetcattyTerminalInterruptTrace {
|
||||
debug?: boolean;
|
||||
traceId?: string;
|
||||
source?: string;
|
||||
sessionId?: string;
|
||||
rendererKeyAt?: number;
|
||||
rendererSendAt?: number;
|
||||
rendererStatus?: string;
|
||||
rendererHasSelection?: boolean;
|
||||
rendererPriority?: {
|
||||
sessionId: string | null;
|
||||
backlogBytes: number;
|
||||
writeQueueDepth: number;
|
||||
deferredAckBytes: number;
|
||||
ackAfterInputBytes: number;
|
||||
scheduledBackendResume: boolean;
|
||||
skippedReason?: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface NetcattyTerminalOutputPerfMeta {
|
||||
id: string;
|
||||
emittedAt: number;
|
||||
sessionId?: string;
|
||||
chars: number;
|
||||
lineFeeds: number;
|
||||
}
|
||||
|
||||
interface NetcattyBridge {
|
||||
getWindowsPtyInfo?(): NetcattyWindowsPtyInfo | null;
|
||||
startSSHSession(options: NetcattySSHOptions): Promise<string>;
|
||||
startTelnetSession?(options: {
|
||||
sessionId?: string;
|
||||
hostname: string;
|
||||
port?: number;
|
||||
username?: string;
|
||||
password?: string;
|
||||
cols?: number;
|
||||
rows?: number;
|
||||
charset?: string;
|
||||
env?: Record<string, string>;
|
||||
sessionLog?: { enabled: boolean; directory: string; format: string; timestampsEnabled?: boolean };
|
||||
}): Promise<string>;
|
||||
startMoshSession?(options: {
|
||||
sessionId?: string;
|
||||
hostname: string;
|
||||
username?: string;
|
||||
password?: string;
|
||||
privateKey?: string;
|
||||
certificate?: string;
|
||||
keyId?: string;
|
||||
passphrase?: string;
|
||||
authMethod?: import("../../domain/models").HostAuthMethod;
|
||||
requiresMfa?: boolean;
|
||||
identityFilePaths?: string[];
|
||||
useSshAgent?: boolean;
|
||||
agentPublicKeys?: string[];
|
||||
identityAgent?: string;
|
||||
identitiesOnly?: boolean;
|
||||
addKeysToAgent?: string;
|
||||
useKeychain?: boolean;
|
||||
port?: number;
|
||||
moshServerPath?: string;
|
||||
moshClientPath?: string;
|
||||
agentForwarding?: boolean;
|
||||
sudoAutofillPassword?: string;
|
||||
// Algorithm settings, forwarded so the host-info stats companion SSH
|
||||
// connection (issue #1198) negotiates the same KEX / cipher / host-key
|
||||
// set the interactive session would.
|
||||
legacyAlgorithms?: boolean;
|
||||
skipEcdsaHostKey?: boolean;
|
||||
algorithmOverrides?: import("../../domain/models").HostAlgorithmOverrides;
|
||||
// Known hosts, used to verify the host key before the stats companion
|
||||
// connection (issue #1198) sends a saved password.
|
||||
knownHosts?: import("../../domain/models").KnownHost[];
|
||||
verifyHostKeys?: boolean;
|
||||
cols?: number;
|
||||
rows?: number;
|
||||
charset?: string;
|
||||
env?: Record<string, string>;
|
||||
sessionLog?: { enabled: boolean; directory: string; format: string; timestampsEnabled?: boolean };
|
||||
}): Promise<string>;
|
||||
startEtSession?(options: {
|
||||
sessionId?: string;
|
||||
hostname: string;
|
||||
hostId?: string;
|
||||
username?: string;
|
||||
password?: string;
|
||||
privateKey?: string;
|
||||
certificate?: string;
|
||||
keyId?: string;
|
||||
passphrase?: string;
|
||||
authMethod?: import("../../domain/models").HostAuthMethod;
|
||||
requiresMfa?: boolean;
|
||||
identityFilePaths?: string[];
|
||||
useSshAgent?: boolean;
|
||||
agentPublicKeys?: string[];
|
||||
identityAgent?: string;
|
||||
identitiesOnly?: boolean;
|
||||
addKeysToAgent?: string;
|
||||
useKeychain?: boolean;
|
||||
port?: number;
|
||||
etPort?: number;
|
||||
legacyAlgorithms?: boolean;
|
||||
skipEcdsaHostKey?: boolean;
|
||||
algorithmOverrides?: import("../../domain/models").HostAlgorithmOverrides;
|
||||
knownHosts?: import("../../domain/models").KnownHost[];
|
||||
verifyHostKeys?: boolean;
|
||||
jumpHosts?: NetcattyJumpHost[];
|
||||
agentForwarding?: boolean;
|
||||
sudoAutofillPassword?: string;
|
||||
cols?: number;
|
||||
rows?: number;
|
||||
charset?: string;
|
||||
env?: Record<string, string>;
|
||||
sessionLog?: { enabled: boolean; directory: string; format: string; timestampsEnabled?: boolean };
|
||||
}): Promise<string>;
|
||||
startLocalSession?(options: {
|
||||
sessionId?: string;
|
||||
cols?: number;
|
||||
rows?: number;
|
||||
shell?: string;
|
||||
shellArgs?: string[];
|
||||
cwd?: string;
|
||||
env?: Record<string, string>;
|
||||
sessionLog?: { enabled: boolean; directory: string; format: string; timestampsEnabled?: boolean };
|
||||
bootEpoch?: number;
|
||||
}): Promise<string>;
|
||||
startSerialSession?(options: {
|
||||
sessionId?: string;
|
||||
path: string;
|
||||
baudRate?: number;
|
||||
dataBits?: 5 | 6 | 7 | 8;
|
||||
stopBits?: 1 | 1.5 | 2;
|
||||
parity?: 'none' | 'even' | 'odd' | 'mark' | 'space';
|
||||
flowControl?: 'none' | 'xon/xoff' | 'rts/cts';
|
||||
charset?: string;
|
||||
sessionLog?: { enabled: boolean; directory: string; format: string; timestampsEnabled?: boolean };
|
||||
}): Promise<string>;
|
||||
listSerialPorts?(): Promise<Array<{
|
||||
path: string;
|
||||
manufacturer: string;
|
||||
serialNumber: string;
|
||||
vendorId: string;
|
||||
productId: string;
|
||||
pnpId: string;
|
||||
}>>;
|
||||
sendSerialYmodem?(sessionId: string, filePath: string): Promise<{
|
||||
success: boolean;
|
||||
fileName?: string;
|
||||
totalBytes?: number;
|
||||
writtenBytes?: number;
|
||||
error?: string;
|
||||
code?: string;
|
||||
}>;
|
||||
receiveSerialYmodem?(sessionId: string, destinationDir: string): Promise<{
|
||||
success: boolean;
|
||||
files?: Array<{
|
||||
fileName: string;
|
||||
filePath: string;
|
||||
totalBytes: number;
|
||||
writtenBytes: number;
|
||||
}>;
|
||||
fileCount?: number;
|
||||
fileName?: string;
|
||||
filePath?: string;
|
||||
totalBytes?: number;
|
||||
writtenBytes?: number;
|
||||
error?: string;
|
||||
code?: string;
|
||||
}>;
|
||||
getDefaultShell?(): Promise<string>;
|
||||
discoverShells?(): Promise<DiscoveredShell[]>;
|
||||
validatePath?(path: string, type?: 'file' | 'directory' | 'any'): Promise<{ exists: boolean; isFile: boolean; isDirectory: boolean; isExecutable: boolean }>;
|
||||
generateKeyPair?(options: {
|
||||
type: 'RSA' | 'ECDSA' | 'ED25519';
|
||||
bits?: number;
|
||||
comment?: string;
|
||||
}): Promise<{ success: boolean; privateKey?: string; publicKey?: string; error?: string }>;
|
||||
checkSshAgent?(options?: {
|
||||
identityAgent?: string;
|
||||
agentForwarding?: boolean;
|
||||
hostname?: string;
|
||||
port?: number;
|
||||
username?: string;
|
||||
}): Promise<{ running: boolean; startupType: string | null; error: string | null }>;
|
||||
getDefaultKeys?(): Promise<Array<{ name: string; path: string }>>;
|
||||
execCommand(options: {
|
||||
hostname: string;
|
||||
hostId?: string;
|
||||
username: string;
|
||||
port?: number;
|
||||
authMethod?: import("../../domain/models").HostAuthMethod;
|
||||
requiresMfa?: boolean;
|
||||
password?: string;
|
||||
privateKey?: string;
|
||||
certificate?: string;
|
||||
publicKey?: string;
|
||||
keyId?: string;
|
||||
keySource?: 'generated' | 'imported' | 'reference';
|
||||
identityFilePaths?: string[];
|
||||
useSshAgent?: boolean;
|
||||
agentPublicKeys?: string[];
|
||||
identityAgent?: string;
|
||||
identitiesOnly?: boolean;
|
||||
addKeysToAgent?: string;
|
||||
useKeychain?: boolean;
|
||||
passphrase?: string;
|
||||
command: string;
|
||||
timeout?: number;
|
||||
sshTcpConnectTimeoutMs?: number;
|
||||
sshAuthReadyTimeoutMs?: number;
|
||||
enableKeyboardInteractive?: boolean;
|
||||
sessionId?: string;
|
||||
legacyAlgorithms?: boolean;
|
||||
skipEcdsaHostKey?: boolean;
|
||||
algorithmOverrides?: import("../../domain/models").HostAlgorithmOverrides;
|
||||
}): Promise<{ stdout: string; stderr: string; code: number | null }>;
|
||||
/** Get current working directory from an active SSH session */
|
||||
getSessionPwd?(
|
||||
sessionId: string,
|
||||
options?: {
|
||||
allowHomeFallback?: boolean;
|
||||
allowLoginShellFallback?: boolean;
|
||||
timeoutMs?: number;
|
||||
},
|
||||
): Promise<{ success: boolean; cwd?: string; error?: string }>;
|
||||
/**
|
||||
* Get metadata about an already-connected SSH session — currently the
|
||||
* SSH server identification string (the `software` part of the
|
||||
* SSH-2.0 banner). Used to classify network-device vendors from the
|
||||
* banner without opening any additional exec channel.
|
||||
*/
|
||||
getSessionRemoteInfo?(sessionId: string): Promise<{
|
||||
success: boolean;
|
||||
remoteSshVersion?: string;
|
||||
error?: string;
|
||||
}>;
|
||||
/**
|
||||
* Probe the remote distro by running
|
||||
* `cat /etc/os-release 2>/dev/null || uname -a` on the existing SSH
|
||||
* connection's exec channel (not a brand-new connection). Used as a
|
||||
* fallback when banner classification could not identify a network
|
||||
* device vendor and we still want a distro-specific icon.
|
||||
*/
|
||||
getSessionDistroInfo?(sessionId: string): Promise<{
|
||||
success: boolean;
|
||||
stdout?: string;
|
||||
stderr?: string;
|
||||
error?: string;
|
||||
}>;
|
||||
/** Read the remote host's shell history file via an exec channel. */
|
||||
readRemoteHistory?(sessionId: string, limit?: number): Promise<{
|
||||
success: boolean;
|
||||
pending?: boolean;
|
||||
error?: string;
|
||||
shell?: string;
|
||||
bash?: string;
|
||||
zsh?: string;
|
||||
fish?: string;
|
||||
}>;
|
||||
/** Get server stats (CPU, Memory, Disk, Network) from an active SSH session */
|
||||
getServerStats?(sessionId: string): Promise<{
|
||||
success: boolean;
|
||||
// Transient "not ready yet" (e.g. a Mosh session whose SSH handshake is
|
||||
// still in progress, #1198). Callers should keep polling and NOT count
|
||||
// this toward any consecutive-failure give-up.
|
||||
pending?: boolean;
|
||||
error?: string;
|
||||
stats?: {
|
||||
cpu: number | null; // CPU usage percentage (0-100)
|
||||
cpuCores: number | null; // Number of CPU cores
|
||||
cpuPerCore: number[]; // Per-core CPU usage array
|
||||
memTotal: number | null; // Total memory in MB
|
||||
memUsed: number | null; // Used memory in MB (excluding buffers/cache)
|
||||
memFree: number | null; // Free memory in MB
|
||||
memBuffers: number | null; // Buffers in MB
|
||||
memCached: number | null; // Cached in MB
|
||||
swapTotal: number | null; // Total swap in MB
|
||||
swapUsed: number | null; // Used swap in MB
|
||||
topProcesses: Array<{ // Top 10 processes by memory
|
||||
pid: string;
|
||||
memPercent: number;
|
||||
command: string;
|
||||
}>;
|
||||
diskPercent: number | null; // Disk usage percentage for root partition
|
||||
diskUsed: number | null; // Disk used in GB
|
||||
diskTotal: number | null; // Total disk in GB
|
||||
disks: Array<{ // All mounted disks
|
||||
capacityKey?: string; // Filesystem or shared-pool identity
|
||||
mountPoint: string;
|
||||
used: number; // Used in GB
|
||||
total: number; // Total in GB
|
||||
percent: number; // Usage percentage
|
||||
filesystemType?: string; // Filesystem type reported by df
|
||||
}>;
|
||||
netRxSpeed: number; // Total network receive speed (bytes/sec)
|
||||
netTxSpeed: number; // Total network transmit speed (bytes/sec)
|
||||
latencyMs: number | null; // TCP connection establishment latency to the SSH endpoint
|
||||
netInterfaces: Array<{ // Per-interface network stats
|
||||
name: string; // Interface name (e.g., eth0, ens33)
|
||||
rxBytes: number; // Total received bytes
|
||||
txBytes: number; // Total transmitted bytes
|
||||
rxSpeed: number; // Receive speed (bytes/sec)
|
||||
txSpeed: number; // Transmit speed (bytes/sec)
|
||||
}>;
|
||||
hostname?: string; // Hostname reported by the server
|
||||
osName?: string; // Friendly OS name when available
|
||||
kernelRelease?: string; // Kernel release from uname
|
||||
uptimeSeconds?: number | null; // Server uptime in seconds
|
||||
loadAverage?: number[]; // 1/5/15-minute load average
|
||||
};
|
||||
}>;
|
||||
setSessionEncoding?(sessionId: string, encoding: string): Promise<{ ok: boolean; encoding: string }>;
|
||||
writeToSession(
|
||||
sessionId: string,
|
||||
data: string,
|
||||
options?: {
|
||||
automated?: boolean;
|
||||
/** Host-classified secret/no-echo input; always bypasses plugin observers and interceptors. */
|
||||
sensitive?: boolean;
|
||||
lineDelayMs?: number;
|
||||
logRewrite?: { sentCommand: string; displayCommand: string };
|
||||
},
|
||||
): void;
|
||||
interruptSession?(sessionId: string, trace?: NetcattyTerminalInterruptTrace): void;
|
||||
resizeSession(sessionId: string, cols: number, rows: number): void;
|
||||
/**
|
||||
* Sync Windows ConPTY after the renderer clears the xterm viewport.
|
||||
* No-op for SSH and non-ConPTY sessions.
|
||||
*/
|
||||
clearSessionPtyBuffer?(sessionId: string): void;
|
||||
setSessionFlowPaused(sessionId: string, paused: boolean): void;
|
||||
setSessionFlowPausedAndWait?(sessionId: string, paused: boolean): Promise<{ success: boolean; error?: string }>;
|
||||
acquireSessionFlowPauseLease?(sessionId: string): Promise<{
|
||||
success: boolean;
|
||||
leaseId?: string;
|
||||
error?: string;
|
||||
}>;
|
||||
waitSessionFlowPauseLease?(sessionId: string, leaseId: string): Promise<{
|
||||
success: boolean;
|
||||
error?: string;
|
||||
}>;
|
||||
releaseSessionFlowPauseLease?(
|
||||
sessionId: string,
|
||||
leaseId: string,
|
||||
options?: { keepPaused?: boolean },
|
||||
): Promise<{ success: boolean; error?: string }>;
|
||||
onTerminalOutputDrainRequest?(
|
||||
sessionId: string,
|
||||
cb: (payload: { sessionId: string; requestId: string }) => void | Promise<void>,
|
||||
): () => void;
|
||||
respondTerminalOutputDrain?(requestId: string): void;
|
||||
notifyTerminalSessionDisplayReady?(sessionId: string): void;
|
||||
ackSessionFlow(sessionId: string, bytes: number): void;
|
||||
closeSession(sessionId: string, options?: { bootEpoch?: number; retainOwnership?: boolean }): void | Promise<void>;
|
||||
/** Move a live session's output port to this renderer (same PTY). */
|
||||
rebindTerminalSessionOutput?(sessionId: string, authorization: string): Promise<{
|
||||
success: boolean;
|
||||
previousWebContentsId?: number | null;
|
||||
webContentsId?: number;
|
||||
error?: string;
|
||||
}>;
|
||||
/** Restore output after an attach popup closes. */
|
||||
restoreTerminalSessionOutput?(
|
||||
sessionId: string,
|
||||
webContentsId?: number | null,
|
||||
authorization?: string,
|
||||
): Promise<{ success: boolean; restored?: boolean; webContentsId?: number; error?: string }>;
|
||||
/** Ask the home renderer to serialize current terminal scrollback. */
|
||||
requestTerminalSessionSnapshot?(sessionId: string, authorization: string): Promise<{
|
||||
success: boolean;
|
||||
snapshot?: string;
|
||||
kittyKeyboardModeState?: NetcattyKittyKeyboardModeState;
|
||||
kittyKeyboardProtocolEnabled?: boolean;
|
||||
passwordPromptActive?: boolean;
|
||||
cwd?: string | null;
|
||||
title?: string | null;
|
||||
error?: string;
|
||||
}>;
|
||||
/** Home renderer: listen for snapshot requests. */
|
||||
onTerminalSessionSnapshotRequest?(
|
||||
cb: (payload: { sessionId: string; requestId: string }) => void,
|
||||
): () => void;
|
||||
/** Home renderer: reply with serialized scrollback. */
|
||||
respondTerminalSessionSnapshot?(
|
||||
requestId: string,
|
||||
snapshot: string,
|
||||
kittyKeyboardModeState?: NetcattyKittyKeyboardModeState,
|
||||
kittyKeyboardProtocolEnabled?: boolean,
|
||||
passwordPromptActive?: boolean,
|
||||
cwd?: string | null,
|
||||
title?: string | null,
|
||||
): void;
|
||||
/** Observe popup: push current state back to the home renderer before restore. */
|
||||
applyTerminalSessionSnapshot?(
|
||||
sessionId: string,
|
||||
snapshot: string,
|
||||
context: {
|
||||
contextSnapshot: string;
|
||||
contextViewportSnapshot: string;
|
||||
contextScrollbackSnapshot: string;
|
||||
alternateScreen: boolean;
|
||||
kittyKeyboardModeState?: NetcattyKittyKeyboardModeState;
|
||||
kittyKeyboardProtocolEnabled?: boolean;
|
||||
passwordPromptActive?: boolean;
|
||||
cwd?: string | null;
|
||||
title?: string | null;
|
||||
},
|
||||
authorization: string,
|
||||
): Promise<{
|
||||
success: boolean;
|
||||
error?: string;
|
||||
}>;
|
||||
markAttachPopupClosePrepared?(sessionId: string, authorization: string): Promise<{ success: boolean; error?: string }>;
|
||||
onTerminalPopupPrepareClose?(cb: (payload: { sessionId: string; authorization: string }) => void): () => void;
|
||||
/** Home renderer: apply a pushed snapshot from an observe popup. */
|
||||
onTerminalSessionApplySnapshot?(
|
||||
cb: (payload: {
|
||||
sessionId: string;
|
||||
snapshot: string;
|
||||
contextSnapshot: string;
|
||||
contextViewportSnapshot: string;
|
||||
contextScrollbackSnapshot: string;
|
||||
alternateScreen: boolean;
|
||||
kittyKeyboardModeState?: NetcattyKittyKeyboardModeState;
|
||||
kittyKeyboardProtocolEnabled?: boolean;
|
||||
passwordPromptActive?: boolean;
|
||||
cwd?: string | null;
|
||||
title?: string | null;
|
||||
requestId: string;
|
||||
}) => boolean | Promise<boolean>,
|
||||
): () => void;
|
||||
// ZMODEM file transfer
|
||||
onZmodemEvent?(
|
||||
sessionId: string,
|
||||
cb: (event: {
|
||||
type: 'detect' | 'progress' | 'complete' | 'error';
|
||||
sessionId: string;
|
||||
transferType?: 'upload' | 'download';
|
||||
filename?: string;
|
||||
transferred?: number;
|
||||
total?: number;
|
||||
fileIndex?: number;
|
||||
fileCount?: number;
|
||||
finalizing?: boolean;
|
||||
error?: string;
|
||||
}) => void
|
||||
): () => void;
|
||||
cancelZmodem?(sessionId: string, options?: { interrupt?: boolean }): void;
|
||||
startZmodemDragDropUpload?(
|
||||
sessionId: string,
|
||||
files: Array<{
|
||||
path?: string;
|
||||
name: string;
|
||||
remoteName: string;
|
||||
data?: ArrayBuffer;
|
||||
}>,
|
||||
uploadCommand?: string,
|
||||
): Promise<{ success: boolean; error?: string }>;
|
||||
onZmodemOverwriteRequest?(
|
||||
sessionId: string,
|
||||
cb: (payload: { sessionId: string; requestId: string; filename: string }) => void
|
||||
): () => void;
|
||||
respondZmodemOverwrite?(payload: {
|
||||
requestId: string;
|
||||
action: "overwrite" | "skip" | "cancel";
|
||||
applyToRest: boolean;
|
||||
}): void;
|
||||
onSessionData(
|
||||
sessionId: string,
|
||||
cb: (
|
||||
data: string,
|
||||
meta?: {
|
||||
droppedOutputMayAffectTerminalState?: boolean;
|
||||
droppedOutputAlternateScreenAction?: "enter" | "leave";
|
||||
/** True while Mosh is still on the ephemeral SSH handshake PTY. */
|
||||
moshHandshake?: boolean;
|
||||
/** The Mosh SSH bootstrap is blocked on input that Netcatty cannot answer automatically. */
|
||||
moshHandshakeRequiresUserInput?: boolean;
|
||||
terminalPerf?: NetcattyTerminalOutputPerfMeta;
|
||||
/** Original host output units acknowledged even when an interceptor changes display length. */
|
||||
pluginPipelineIngressBytes?: number;
|
||||
/** Host-owned provenance marker for output already processed by an interceptor. */
|
||||
pluginPipelineProcessed?: boolean;
|
||||
/** Host-classified authentication prompt state for protecting subsequent input. */
|
||||
pluginPipelineSensitiveInput?: boolean;
|
||||
/** Host-owned marker that a Plugin connection Provider has explicitly reached connected status. */
|
||||
pluginConnectionReady?: boolean;
|
||||
},
|
||||
) => void,
|
||||
options?: { replayBacklog?: boolean },
|
||||
): () => void;
|
||||
onSessionExit(
|
||||
sessionId: string,
|
||||
cb: (evt: { exitCode?: number; signal?: number; error?: string; reason?: "exited" | "error" | "timeout" | "closed" }) => void
|
||||
): () => void;
|
||||
onTelnetAutoLoginComplete?(
|
||||
sessionId: string,
|
||||
cb: (evt: { sessionId: string; bootEpoch?: number }) => void
|
||||
): () => void;
|
||||
onTelnetAutoLoginCancelled?(
|
||||
sessionId: string,
|
||||
cb: (evt: { sessionId: string; bootEpoch?: number }) => void
|
||||
): () => void;
|
||||
/** Fires after Mosh swaps from the SSH handshake PTY to mosh-client. */
|
||||
onMoshSessionReady?(
|
||||
sessionId: string,
|
||||
cb: (evt: { sessionId: string; bootEpoch?: number }) => void
|
||||
): () => void;
|
||||
onTelnetEchoMode?(
|
||||
sessionId: string,
|
||||
cb: (evt: { sessionId: string; remoteEcho: boolean; localEcho: boolean }) => void
|
||||
): () => void;
|
||||
getTelnetEchoMode?(sessionId: string): Promise<{
|
||||
success: boolean;
|
||||
sessionId?: string;
|
||||
remoteEcho?: boolean;
|
||||
localEcho?: boolean;
|
||||
error?: string;
|
||||
}>;
|
||||
onAuthFailed?(
|
||||
sessionId: string,
|
||||
cb: (evt: { sessionId: string; error: string; hostname: string }) => void
|
||||
): () => void;
|
||||
|
||||
// Keyboard-interactive authentication (2FA/MFA)
|
||||
onKeyboardInteractive?(
|
||||
cb: (request: {
|
||||
requestId: string;
|
||||
sessionId: string;
|
||||
hostId?: string;
|
||||
name: string;
|
||||
instructions: string;
|
||||
prompts: Array<{ prompt: string; echo: boolean }>;
|
||||
hostname: string;
|
||||
savedPassword?: string | null;
|
||||
/** When false, UI must not offer saving the response as the host password. */
|
||||
allowSavePassword?: boolean;
|
||||
scope?: "terminal" | "external";
|
||||
bootEpoch?: number;
|
||||
}) => void
|
||||
): () => void;
|
||||
onKeyboardInteractiveCancelled?(
|
||||
cb: (event: {
|
||||
requestId: string;
|
||||
sessionId?: string;
|
||||
reason?: string;
|
||||
}) => void
|
||||
): () => void;
|
||||
respondKeyboardInteractive?(
|
||||
requestId: string,
|
||||
responses: string[],
|
||||
cancelled?: boolean
|
||||
): Promise<{ success: boolean; error?: string }>;
|
||||
|
||||
onHostKeyVerification?(
|
||||
cb: (request: {
|
||||
requestId: string;
|
||||
sessionId: string;
|
||||
hostname: string;
|
||||
port: number;
|
||||
status: 'unknown' | 'changed';
|
||||
keyType: string;
|
||||
fingerprint: string;
|
||||
publicKey?: string;
|
||||
knownHostId?: string;
|
||||
knownFingerprint?: string;
|
||||
bootEpoch?: number;
|
||||
}) => void
|
||||
): () => void;
|
||||
respondHostKeyVerification?(
|
||||
requestId: string,
|
||||
accept: boolean,
|
||||
addToKnownHosts?: boolean
|
||||
): Promise<{ success: boolean; error?: string }>;
|
||||
|
||||
// Passphrase request for encrypted SSH keys
|
||||
onPassphraseRequest?(
|
||||
cb: (request: {
|
||||
requestId: string;
|
||||
keyPath: string;
|
||||
keyName: string;
|
||||
hostname?: string;
|
||||
passphraseInvalid?: boolean;
|
||||
sessionId?: string;
|
||||
bootEpoch?: number;
|
||||
}) => void
|
||||
): () => void;
|
||||
respondPassphrase?(
|
||||
requestId: string,
|
||||
passphrase: string,
|
||||
cancelled?: boolean
|
||||
): Promise<{ success: boolean; error?: string }>;
|
||||
respondPassphraseSkip?(
|
||||
requestId: string
|
||||
): Promise<{ success: boolean; error?: string }>;
|
||||
onPassphraseTimeout?(
|
||||
cb: (event: { requestId: string }) => void
|
||||
): () => void;
|
||||
onPassphraseCancelled?(
|
||||
cb: (event: { requestId: string; reason?: string }) => void
|
||||
): () => void;
|
||||
onPassphraseAuthFailed?(
|
||||
cb: (event: { keyPaths: string[]; keyIds?: string[] }) => void
|
||||
): () => void;
|
||||
}
|
||||
}
|
||||
|
||||
export {};
|
||||
197
types/global/netcatty-bridge-sftp.d.ts
vendored
Normal file
197
types/global/netcatty-bridge-sftp.d.ts
vendored
Normal file
@@ -0,0 +1,197 @@
|
||||
import type { RemoteFile, SftpFilenameEncoding, TransferDirection } from "../../types";
|
||||
|
||||
declare global {
|
||||
interface NetcattyBridge {
|
||||
// SFTP operations
|
||||
openSftp(options: NetcattySSHOptions): Promise<string>;
|
||||
openSftpForSession?(sessionId: string, options?: NetcattySSHOptions): Promise<string>;
|
||||
listSftp(sftpId: string, path: string, encoding?: SftpFilenameEncoding): Promise<RemoteFile[]>;
|
||||
realpathSftp?(sftpId: string, path: string, encoding?: SftpFilenameEncoding): Promise<string>;
|
||||
readSftp(sftpId: string, path: string, encoding?: SftpFilenameEncoding): Promise<string>;
|
||||
readSftpBinary?(sftpId: string, path: string, encoding?: SftpFilenameEncoding): Promise<ArrayBuffer>;
|
||||
writeSftp(sftpId: string, path: string, content: string, encoding?: SftpFilenameEncoding): Promise<void>;
|
||||
writeSftpBinary?(sftpId: string, path: string, content: ArrayBuffer, encoding?: SftpFilenameEncoding): Promise<void>;
|
||||
closeSftp(sftpId: string): Promise<void | { success?: boolean; deferred?: boolean; leaseCount?: number }>;
|
||||
retainSftpTransferSession?(sftpId: string, leaseId: string): Promise<{ success: boolean; reason?: string }>;
|
||||
releaseSftpTransferSession?(sftpId: string, leaseId: string): Promise<{ success: boolean; reason?: string }>;
|
||||
mkdirSftp(sftpId: string, path: string, encoding?: SftpFilenameEncoding): Promise<void>;
|
||||
deleteSftp?(
|
||||
sftpId: string,
|
||||
path: string,
|
||||
encoding?: SftpFilenameEncoding,
|
||||
expectedType?: SftpStatResult["type"],
|
||||
): Promise<void>;
|
||||
renameSftp?(sftpId: string, oldPath: string, newPath: string, encoding?: SftpFilenameEncoding): Promise<void>;
|
||||
statSftp?(sftpId: string, path: string, encoding?: SftpFilenameEncoding): Promise<SftpStatResult>;
|
||||
/** No-follow remote metadata for conflict detection (symlink vs target). Missing path → null. */
|
||||
lstatSftp?(sftpId: string, path: string, encoding?: SftpFilenameEncoding): Promise<SftpStatResult | null>;
|
||||
chmodSftp?(sftpId: string, path: string, mode: string, encoding?: SftpFilenameEncoding): Promise<void>;
|
||||
/** Extract a remote archive into its parent directory via SSH exec. */
|
||||
extractSftpArchive?(sftpId: string, path: string, encoding?: SftpFilenameEncoding): Promise<{ success: boolean }>;
|
||||
getSftpHomeDir?(sftpId: string, encoding?: SftpFilenameEncoding): Promise<{ success: boolean; homeDir?: string; error?: string }>;
|
||||
|
||||
// Transfer with progress
|
||||
cancelTransfer?(transferId: string): Promise<void>;
|
||||
/** Clear a pre-start cancel latch so intentional same-id resume/retry can run. */
|
||||
clearPendingTransferCancel?(transferId: string): Promise<{ success: boolean } | void>;
|
||||
sameHostCopyDirectory?(sftpId: string, sourcePath: string, targetPath: string, encoding?: SftpFilenameEncoding, transferId?: string): Promise<{ success: boolean }>;
|
||||
|
||||
// Compressed folder upload
|
||||
startCompressedUpload?(
|
||||
options: {
|
||||
compressionId: string;
|
||||
folderPath: string;
|
||||
targetPath: string;
|
||||
sftpId: string;
|
||||
folderName: string;
|
||||
totalBytes: number;
|
||||
}
|
||||
): Promise<{ compressionId: string; success?: boolean; error?: string }>;
|
||||
cancelCompressedUpload?(compressionId: string): Promise<{ success: boolean }>;
|
||||
pauseCompressedUpload?(compressionId: string): Promise<{ success: boolean; deferred?: boolean; lifecycleEpoch?: number; reason?: string }>;
|
||||
resumeCompressedUpload?(compressionId: string): Promise<{ success: boolean; lifecycleEpoch?: number; reason?: string }>;
|
||||
checkCompressedUploadSupport?(sftpId: string): Promise<{
|
||||
supported: boolean;
|
||||
localTar: boolean;
|
||||
remoteTar: boolean;
|
||||
error?: string;
|
||||
}>;
|
||||
|
||||
// Streaming transfer with real progress and cancellation
|
||||
startStreamTransfer?(
|
||||
options: {
|
||||
transferId: string;
|
||||
sourcePath: string;
|
||||
targetPath: string;
|
||||
sourceType: 'local' | 'sftp';
|
||||
targetType: 'local' | 'sftp';
|
||||
sourceSftpId?: string;
|
||||
targetSftpId?: string;
|
||||
sourceHostId?: string;
|
||||
targetHostId?: string;
|
||||
parentTaskId?: string;
|
||||
directoryEntryIndex?: number;
|
||||
directoryEntryIdentity?: string;
|
||||
totalBytes?: number;
|
||||
sourceEncoding?: SftpFilenameEncoding;
|
||||
targetEncoding?: SftpFilenameEncoding;
|
||||
sameHost?: boolean;
|
||||
resumable?: boolean;
|
||||
checkpointBytes?: number;
|
||||
resumeStage?: 'direct' | 'download' | 'upload';
|
||||
downloadCheckpointBytes?: number;
|
||||
uploadCheckpointBytes?: number;
|
||||
sourceFingerprint?: string;
|
||||
lifecycleEpoch?: number;
|
||||
lifecycleState?: 'queued' | 'pausing' | 'paused' | 'transferring';
|
||||
pauseUnavailableReason?: string;
|
||||
globalConcurrency?: number;
|
||||
/** When true, skip main-process admission (renderer already scheduled). */
|
||||
skipAdmission?: boolean;
|
||||
}
|
||||
): Promise<{ transferId: string; totalBytes?: number; error?: string; cancelled?: boolean }>;
|
||||
pauseTransfer?(transferId: string): Promise<{
|
||||
success: boolean;
|
||||
superseded?: boolean;
|
||||
supersededBy?: "pause" | "resume" | "cancel";
|
||||
checkpointBytes?: number;
|
||||
resumeStage?: 'direct' | 'download' | 'upload';
|
||||
downloadCheckpointBytes?: number;
|
||||
uploadCheckpointBytes?: number;
|
||||
sourceFingerprint?: string;
|
||||
lifecycleEpoch?: number;
|
||||
reason?: string;
|
||||
}>;
|
||||
resumeTransfer?(transferId: string): Promise<{ success: boolean; reason?: string; lifecycleEpoch?: number; superseded?: boolean; supersededBy?: "pause" | "resume" | "cancel" }>;
|
||||
prioritizeTransfer?(transferId: string): Promise<{ success: boolean }>;
|
||||
setGlobalTransferConcurrency?(limit: number): Promise<{ success: boolean; limit: number }>;
|
||||
cleanupTransferArtifacts?(payload: {
|
||||
transferId: string;
|
||||
sourcePath: string;
|
||||
targetPath: string;
|
||||
targetSftpId?: string;
|
||||
targetEncoding?: SftpFilenameEncoding;
|
||||
stagedTargetPath?: string;
|
||||
}): Promise<{ success: boolean }>;
|
||||
onGlobalSftpTransferEvent?(callback: (event: {
|
||||
type: 'queued' | 'started' | 'progress' | 'pausing' | 'paused' | 'resumed' | 'cancelled' | 'completed' | 'failed';
|
||||
transferId: string;
|
||||
direction?: TransferDirection;
|
||||
fileName?: string;
|
||||
sourcePath?: string;
|
||||
targetPath?: string;
|
||||
startedAt?: number;
|
||||
endedAt?: number;
|
||||
error?: string;
|
||||
transferred?: number;
|
||||
totalBytes?: number;
|
||||
speed?: number;
|
||||
checkpointBytes?: number;
|
||||
resumeStage?: 'direct' | 'download' | 'upload';
|
||||
downloadCheckpointBytes?: number;
|
||||
uploadCheckpointBytes?: number;
|
||||
sourceFingerprint?: string;
|
||||
isDirectory?: boolean;
|
||||
controlKind?: 'stream' | 'compressed-upload';
|
||||
phase?: 'scanning' | 'compressing' | 'uploading' | 'transferring' | 'extracting' | 'verifying';
|
||||
sessionId?: string;
|
||||
sourceHostId?: string;
|
||||
targetHostId?: string;
|
||||
parentTaskId?: string;
|
||||
directoryEntryIndex?: number;
|
||||
directoryEntryIdentity?: string;
|
||||
lifecycleEpoch?: number;
|
||||
lifecycleState?: 'queued' | 'pausing' | 'paused' | 'transferring';
|
||||
resumable?: boolean;
|
||||
pauseUnavailableReason?: string;
|
||||
}) => void): () => void;
|
||||
|
||||
// Local filesystem operations
|
||||
listLocalDir?(path: string): Promise<RemoteFile[]>;
|
||||
readLocalFile?(path: string, options?: { maxBytes?: number }): Promise<ArrayBuffer>;
|
||||
writeLocalFile?(path: string, content: ArrayBuffer): Promise<void>;
|
||||
deleteLocalFile?(path: string, expectedType?: SftpStatResult["type"]): Promise<void>;
|
||||
renameLocalFile?(oldPath: string, newPath: string): Promise<void>;
|
||||
extractLocalArchive?(path: string): Promise<{ success: boolean }>;
|
||||
mkdirLocal?(path: string): Promise<void>;
|
||||
statLocal?(path: string): Promise<SftpStatResult>;
|
||||
/** No-follow local metadata for conflict detection (symlink vs target). */
|
||||
lstatLocal?(path: string): Promise<SftpStatResult>;
|
||||
listLocalTree?(
|
||||
path: string,
|
||||
options?: {
|
||||
onProgress?: (progress: {
|
||||
fileCount: number;
|
||||
directoryCount: number;
|
||||
entryCount: number;
|
||||
}) => void;
|
||||
/** Stream discovered rows while the walk continues (edge-scan/upload). */
|
||||
onEntries?: (entries: Array<{
|
||||
localPath: string;
|
||||
relativePath: string;
|
||||
type: 'file' | 'directory';
|
||||
size: number;
|
||||
lastModified: number;
|
||||
}>) => void;
|
||||
/** Renderer-generated ID used by cancelLocalTreeScan. */
|
||||
scanId?: string;
|
||||
limits?: {
|
||||
maxDirectories?: number;
|
||||
maxEntries?: number;
|
||||
};
|
||||
},
|
||||
): Promise<Array<{
|
||||
localPath: string;
|
||||
relativePath: string;
|
||||
type: 'file' | 'directory';
|
||||
size: number;
|
||||
lastModified: number;
|
||||
}>>;
|
||||
cancelLocalTreeScan?(scanId: string): Promise<void>;
|
||||
getHomeDir?(): Promise<string>;
|
||||
listDrives?(): Promise<string[]>;
|
||||
getSystemInfo?(): Promise<{ username: string; hostname: string }>;
|
||||
}
|
||||
}
|
||||
|
||||
export {};
|
||||
364
types/global/netcatty-bridge-sync.d.ts
vendored
Normal file
364
types/global/netcatty-bridge-sync.d.ts
vendored
Normal file
@@ -0,0 +1,364 @@
|
||||
import type { S3Config, SyncedFile, WebDAVConfig } from "../../domain/sync";
|
||||
import type { AppLockSettings } from "../../domain/appLock";
|
||||
|
||||
type AppLockRuntimeReason = 'startup' | 'idle' | 'manual' | 'background' | null;
|
||||
|
||||
interface AppLockRuntimeState {
|
||||
initialized: boolean;
|
||||
locked: boolean;
|
||||
reason: AppLockRuntimeReason;
|
||||
version: number;
|
||||
lastLockedAt: number | null;
|
||||
lastUnlockedAt: number | null;
|
||||
lastActivityAt: number | null;
|
||||
}
|
||||
|
||||
type AppLockSettingsMutationError =
|
||||
| { ok: false; error: 'empty-current' | 'empty-next' | 'incorrect' };
|
||||
|
||||
type AppLockUnlockResult =
|
||||
| { ok: true }
|
||||
| { ok: false; error: 'empty' | 'incorrect' };
|
||||
|
||||
type AppLockSystemUnlockStatus = {
|
||||
supported: boolean;
|
||||
available: boolean;
|
||||
enabled: boolean;
|
||||
platform: 'darwin' | 'win32' | 'unsupported';
|
||||
label: 'Touch ID' | 'Windows Hello' | null;
|
||||
reason: string | null;
|
||||
};
|
||||
|
||||
type AppLockSystemUnlockResult =
|
||||
| { ok: true }
|
||||
| { ok: false; error: 'disabled' | 'not-locked' | 'unsupported' | 'unavailable' | 'cancelled' | 'failed' };
|
||||
|
||||
type AppLockSystemUnlockSettingsResult =
|
||||
| AppLockSettings
|
||||
| { ok: false; error: 'empty-current' | 'incorrect' | 'locked' | 'unsupported' | 'unavailable' | 'cancelled' | 'failed' };
|
||||
|
||||
declare global {
|
||||
interface NetcattyBridge {
|
||||
setTheme?(theme: 'light' | 'dark' | 'system'): Promise<boolean>;
|
||||
setBackgroundColor?(color: string): Promise<boolean>;
|
||||
setWindowOpacity?(opacity: number): Promise<boolean>;
|
||||
setAppIconVariant?(variant: import('../../domain/appIconVariant').AppIconVariant): Promise<boolean>;
|
||||
setLanguage?(language: string): Promise<boolean>;
|
||||
// Window controls for custom title bar (Windows/Linux)
|
||||
windowMinimize?(): Promise<void>;
|
||||
windowMaximize?(): Promise<boolean>;
|
||||
windowClose?(): Promise<void>;
|
||||
windowIsMaximized?(): Promise<boolean>;
|
||||
windowIsFullscreen?(): Promise<boolean>;
|
||||
windowFocus?(): Promise<boolean>;
|
||||
setTerminalKeyboardFocus?(focused: boolean): void;
|
||||
setWindowTitle?(title: string): Promise<boolean>;
|
||||
openSessionInNewWindow?(payload: {
|
||||
title: string;
|
||||
sourceSession: import("../../domain/models").TerminalSession;
|
||||
localShellType?: import("../../domain/models").TerminalSession['shellType'];
|
||||
}): Promise<{ success: boolean; error?: string }>;
|
||||
onOpenSessionInNewWindow?(cb: (payload: {
|
||||
title: string;
|
||||
sourceSession: import("../../domain/models").TerminalSession;
|
||||
localShellType?: import("../../domain/models").TerminalSession['shellType'];
|
||||
}) => void): () => void;
|
||||
onWindowCommandCloseRequested?(cb: () => void): () => void;
|
||||
onWindowFullScreenChanged?(cb: (isFullscreen: boolean) => void): () => void;
|
||||
onWindowShown?(cb: () => void): () => void;
|
||||
onWindowFocusRequested?(cb: () => void): () => void;
|
||||
onWindowWillHide?(cb: () => void): () => void;
|
||||
|
||||
// Settings window
|
||||
openSettingsWindow?(): Promise<boolean>;
|
||||
closeSettingsWindow?(): Promise<void>;
|
||||
|
||||
// Cross-window settings sync
|
||||
notifySettingsChanged?(payload: { key: string; value: unknown }): void;
|
||||
onSettingsChanged?(cb: (payload: { key: string; value: unknown }) => void): () => void;
|
||||
getAppLockRuntimeState?(): Promise<AppLockRuntimeState>;
|
||||
getAppLockSettings?(): Promise<AppLockSettings>;
|
||||
setAppLockTimeoutMinutes?(timeoutMinutes: number): Promise<AppLockSettings>;
|
||||
requestAppLockEnable?(): Promise<AppLockSettings | AppLockSettingsMutationError>;
|
||||
requestAppLockDisable?(currentPassword: string): Promise<AppLockSettings | AppLockSettingsMutationError>;
|
||||
requestAppLockReset?(currentPassword: string): Promise<AppLockSettings | AppLockSettingsMutationError>;
|
||||
requestAppLockPasswordChange?(input: {
|
||||
currentPassword?: string;
|
||||
nextPassword: string;
|
||||
}): Promise<AppLockSettings | AppLockSettingsMutationError>;
|
||||
setAppLockRuntimeLocked?(reason: Exclude<AppLockRuntimeReason, null>): Promise<AppLockRuntimeState>;
|
||||
requestAppLockUnlock?(password: string): Promise<AppLockUnlockResult>;
|
||||
getAppLockSystemUnlockStatus?(): Promise<AppLockSystemUnlockStatus>;
|
||||
setAppLockSystemUnlockEnabled?(input: {
|
||||
enabled: boolean;
|
||||
currentPassword?: string;
|
||||
autoPromptEnabled?: boolean;
|
||||
}): Promise<AppLockSystemUnlockSettingsResult>;
|
||||
requestAppLockSystemUnlock?(): Promise<AppLockSystemUnlockResult>;
|
||||
reportAppLockActivity?(): Promise<void>;
|
||||
onAppLockSettingsChanged?(cb: (settings: AppLockSettings) => void): () => void;
|
||||
onAppLockRuntimeStateChanged?(cb: (state: AppLockRuntimeState) => void): () => void;
|
||||
|
||||
// Cloud sync master password (stored in-memory + persisted via Electron safeStorage)
|
||||
cloudSyncSetSessionPassword?(password: string): Promise<boolean>;
|
||||
cloudSyncGetSessionPassword?(): Promise<string | null>;
|
||||
onCloudSyncSessionPasswordAvailable?(callback: () => void): () => void;
|
||||
cloudSyncClearSessionPassword?(): Promise<boolean>;
|
||||
|
||||
// Cloud sync network operations (proxied via main process)
|
||||
cloudSyncWebdavInitialize?(config: WebDAVConfig): Promise<{ resourceId: string | null }>;
|
||||
cloudSyncWebdavUpload?(
|
||||
config: WebDAVConfig,
|
||||
syncedFile: SyncedFile
|
||||
): Promise<{ resourceId: string }>;
|
||||
cloudSyncWebdavDownload?(config: WebDAVConfig): Promise<{ syncedFile: SyncedFile | null }>;
|
||||
cloudSyncWebdavDelete?(config: WebDAVConfig): Promise<{ ok: true }>;
|
||||
|
||||
cloudSyncS3Initialize?(config: S3Config): Promise<{ resourceId: string | null }>;
|
||||
cloudSyncS3Upload?(
|
||||
config: S3Config,
|
||||
syncedFile: SyncedFile
|
||||
): Promise<{ resourceId: string }>;
|
||||
cloudSyncS3Download?(config: S3Config): Promise<{ syncedFile: SyncedFile | null }>;
|
||||
cloudSyncS3Delete?(config: S3Config): Promise<{ ok: true }>;
|
||||
|
||||
// Port Forwarding
|
||||
startPortForward?(options: PortForwardOptions): Promise<PortForwardResult>;
|
||||
stopPortForward?(tunnelId: string): Promise<PortForwardResult>;
|
||||
getPortForwardStatus?(tunnelId: string): Promise<PortForwardStatusResult>;
|
||||
listPortForwards?(): Promise<{ ruleId?: string; tunnelId: string; type: string; status: string; error?: string }[]>;
|
||||
getPortForwardSnapshot?(): Promise<PortForwardRuntimeSnapshot>;
|
||||
subscribePortForwardRuntime?(): Promise<PortForwardRuntimeSnapshot>;
|
||||
unsubscribePortForwardRuntime?(): Promise<{ success: boolean }>;
|
||||
subscribePortForward?(tunnelId: string): Promise<{
|
||||
tunnelId: string;
|
||||
type?: string;
|
||||
status: 'inactive' | 'connecting' | 'active' | 'error';
|
||||
error?: string;
|
||||
}>;
|
||||
stopAllPortForwards?(): Promise<void>;
|
||||
stopPortForwardByRuleId?(ruleId: string): Promise<{
|
||||
stopped: number;
|
||||
failed?: number;
|
||||
errors?: string[];
|
||||
}>;
|
||||
onPortForwardStatus?(tunnelId: string, cb: PortForwardStatusCallback): () => void;
|
||||
onPortForwardRuntime?(cb: PortForwardRuntimeEventCallback): () => void;
|
||||
|
||||
// Known Hosts
|
||||
readKnownHosts?(): Promise<string | null>;
|
||||
|
||||
// Open URL in default browser. Resolves when the URL is handled by
|
||||
// either the system browser or the in-app fallback BrowserWindow.
|
||||
// Rejects only in the rare case where both paths fail.
|
||||
openExternal?(url: string): Promise<void>;
|
||||
openPath?(path: string): Promise<{ success: boolean; error?: string }>;
|
||||
|
||||
// App info (name/version/platform) for About screens
|
||||
getAppInfo?(): Promise<{ name: string; version: string; platform: string }>;
|
||||
ptyGetChildProcesses?(sessionId: string): Promise<Array<{ pid: number; command: string }>>;
|
||||
confirmCloseBusy?(payload: {
|
||||
command: string;
|
||||
title?: string;
|
||||
message?: string;
|
||||
cancelLabel?: string;
|
||||
closeLabel?: string;
|
||||
}): Promise<boolean>;
|
||||
getVaultBackupCapabilities?(): Promise<{ encryptionAvailable: boolean }>;
|
||||
createVaultBackup?(payload: {
|
||||
payload: import('./domain/sync').SyncPayload;
|
||||
reason: 'app_version_change' | 'before_restore';
|
||||
sourceAppVersion?: string;
|
||||
targetAppVersion?: string;
|
||||
syncDataVersion?: number;
|
||||
maxCount?: number;
|
||||
}): Promise<{
|
||||
created: boolean;
|
||||
backup: {
|
||||
id: string;
|
||||
createdAt: number;
|
||||
reason: 'app_version_change' | 'before_restore';
|
||||
sourceAppVersion?: string;
|
||||
targetAppVersion?: string;
|
||||
fingerprint: string;
|
||||
preview: {
|
||||
hostCount: number;
|
||||
keyCount: number;
|
||||
snippetCount: number;
|
||||
noteCount: number;
|
||||
identityCount: number;
|
||||
portForwardingRuleCount: number;
|
||||
};
|
||||
} | null;
|
||||
}>;
|
||||
listVaultBackups?(): Promise<Array<{
|
||||
id: string;
|
||||
createdAt: number;
|
||||
reason: 'app_version_change' | 'before_restore';
|
||||
sourceAppVersion?: string;
|
||||
targetAppVersion?: string;
|
||||
fingerprint: string;
|
||||
preview: {
|
||||
hostCount: number;
|
||||
keyCount: number;
|
||||
snippetCount: number;
|
||||
noteCount: number;
|
||||
identityCount: number;
|
||||
portForwardingRuleCount: number;
|
||||
};
|
||||
}>>;
|
||||
readVaultBackup?(payload: { id: string }): Promise<{
|
||||
backup: {
|
||||
id: string;
|
||||
createdAt: number;
|
||||
reason: 'app_version_change' | 'before_restore';
|
||||
sourceAppVersion?: string;
|
||||
targetAppVersion?: string;
|
||||
fingerprint: string;
|
||||
preview: {
|
||||
hostCount: number;
|
||||
keyCount: number;
|
||||
snippetCount: number;
|
||||
noteCount: number;
|
||||
identityCount: number;
|
||||
portForwardingRuleCount: number;
|
||||
};
|
||||
};
|
||||
payload: import('./domain/sync').SyncPayload;
|
||||
}>;
|
||||
trimVaultBackups?(payload: { maxCount: number }): Promise<{ deletedCount: number; keptCount: number }>;
|
||||
openVaultBackupDir?(): Promise<{ success: boolean; path: string }>;
|
||||
// Subscribe to main-process-driven "vault backups changed" events.
|
||||
// Returns an unsubscribe callback. Undefined in non-Electron builds.
|
||||
onVaultBackupsChanged?(handler: () => void): () => void;
|
||||
|
||||
// Notify main process the renderer has mounted/painted (used to avoid initial blank screen).
|
||||
rendererReady?(): void;
|
||||
// Fired when an existing main renderer window is shown again from tray,
|
||||
// global hotkey, dock activation, or second-instance focusing.
|
||||
onAppLockReopen?(listener: () => void): () => void;
|
||||
|
||||
// Quit guard: subscribe to main-process quit requests that query for dirty editors.
|
||||
// Listener is called with no arguments; return value is an unsubscribe function.
|
||||
onCheckDirtyEditors?(listener: () => void): () => void;
|
||||
// Report the dirty-check result back to the main process.
|
||||
reportDirtyEditorsResult?(hasDirty: boolean): void;
|
||||
|
||||
onLanguageChanged?(cb: (language: string) => void): () => void;
|
||||
|
||||
// Chain progress listener for jump host connections
|
||||
// Callback receives: (sessionId: string, currentHop: number, totalHops: number, hostLabel: string, status: string, error?: string)
|
||||
onChainProgress?(cb: (sessionId: string, hop: number, total: number, label: string, status: string, error?: string) => void): () => void;
|
||||
|
||||
// Fired when a requested SSH connection reuse cannot be honored and the
|
||||
// session falls back to a regular fresh connection.
|
||||
onConnectionReuseFallback?(cb: (sessionId: string, sourceSessionId?: string) => void): () => void;
|
||||
|
||||
// SFTP connection progress listener (auth method logs)
|
||||
onSftpConnectionProgress?(cb: (sessionId: string, label: string, status: string, detail?: string) => void): () => void;
|
||||
|
||||
// OAuth callback server for cloud sync. `prepareOAuthCallback` binds the
|
||||
// loopback listener and returns the chosen port (preferred 45678, falls
|
||||
// back to an OS-assigned free port if busy). The caller then builds the
|
||||
// OAuth URL against `redirectUri`, opens the browser, and finally awaits
|
||||
// the code via `awaitOAuthCallback`.
|
||||
prepareOAuthCallback?(): Promise<{ sessionId: string; port: number; redirectUri: string }>;
|
||||
awaitOAuthCallback?(expectedState?: string, sessionId?: string): Promise<{ code: string; state?: string }>;
|
||||
cancelOAuthCallback?(sessionId?: string): Promise<void>;
|
||||
|
||||
// GitHub Device Flow (cloud sync)
|
||||
githubStartDeviceFlow?(options?: { clientId?: string; scope?: string }): Promise<{
|
||||
deviceCode: string;
|
||||
userCode: string;
|
||||
verificationUri: string;
|
||||
expiresAt: number;
|
||||
interval: number;
|
||||
}>;
|
||||
githubPollDeviceFlowToken?(options: { clientId?: string; deviceCode: string; pollId?: string }): Promise<{
|
||||
access_token?: string;
|
||||
token_type?: string;
|
||||
scope?: string;
|
||||
error?: string;
|
||||
error_description?: string;
|
||||
}>;
|
||||
githubCancelDeviceFlowPoll?(pollId: string): Promise<void>;
|
||||
githubDownloadGistRawContent?(options: { accessToken: string; rawUrl: string }): Promise<string>;
|
||||
|
||||
// Google OAuth (cloud sync) - proxied via main process to avoid CORS
|
||||
googleExchangeCodeForTokens?(options: {
|
||||
clientId: string;
|
||||
clientSecret?: string;
|
||||
code: string;
|
||||
codeVerifier: string;
|
||||
redirectUri: string;
|
||||
}): Promise<{
|
||||
accessToken: string;
|
||||
refreshToken?: string;
|
||||
expiresAt?: number;
|
||||
tokenType: string;
|
||||
scope?: string;
|
||||
}>;
|
||||
googleRefreshAccessToken?(options: {
|
||||
clientId: string;
|
||||
clientSecret?: string;
|
||||
refreshToken: string;
|
||||
}): Promise<{
|
||||
accessToken: string;
|
||||
refreshToken: string;
|
||||
expiresAt?: number;
|
||||
tokenType: string;
|
||||
scope?: string;
|
||||
}>;
|
||||
googleGetUserInfo?(options: { accessToken: string }): Promise<{
|
||||
id: string;
|
||||
email: string;
|
||||
name: string;
|
||||
picture?: string;
|
||||
}>;
|
||||
|
||||
// Google Drive API (cloud sync) - proxied via main process to avoid CORS/COEP issues
|
||||
googleDriveFindSyncFile?(options: { accessToken: string; fileName?: string }): Promise<{ fileId: string | null }>;
|
||||
googleDriveCreateSyncFile?(options: { accessToken: string; fileName?: string; syncedFile: unknown }): Promise<{ fileId: string }>;
|
||||
googleDriveUpdateSyncFile?(options: { accessToken: string; fileId: string; syncedFile: unknown }): Promise<{ ok: true }>;
|
||||
googleDriveDownloadSyncFile?(options: { accessToken: string; fileId: string }): Promise<{ syncedFile: unknown | null }>;
|
||||
googleDriveDeleteSyncFile?(options: { accessToken: string; fileId: string }): Promise<{ ok: true }>;
|
||||
|
||||
// OneDrive OAuth + Graph (cloud sync) - proxied via main process to avoid CORS
|
||||
onedriveExchangeCodeForTokens?(options: {
|
||||
clientId: string;
|
||||
code: string;
|
||||
codeVerifier: string;
|
||||
redirectUri: string;
|
||||
scope?: string;
|
||||
}): Promise<{
|
||||
accessToken: string;
|
||||
refreshToken?: string;
|
||||
expiresAt?: number;
|
||||
tokenType: string;
|
||||
scope?: string;
|
||||
}>;
|
||||
onedriveRefreshAccessToken?(options: {
|
||||
clientId: string;
|
||||
refreshToken: string;
|
||||
scope?: string;
|
||||
}): Promise<{
|
||||
accessToken: string;
|
||||
refreshToken: string;
|
||||
expiresAt?: number;
|
||||
tokenType: string;
|
||||
scope?: string;
|
||||
}>;
|
||||
onedriveGetUserInfo?(options: { accessToken: string }): Promise<{
|
||||
id: string;
|
||||
email: string;
|
||||
name: string;
|
||||
avatarDataUrl?: string;
|
||||
}>;
|
||||
onedriveFindSyncFile?(options: { accessToken: string; fileName?: string }): Promise<{ fileId: string | null }>;
|
||||
onedriveUploadSyncFile?(options: { accessToken: string; fileName?: string; syncedFile: unknown }): Promise<{ fileId: string | null }>;
|
||||
onedriveDownloadSyncFile?(options: { accessToken: string; fileId?: string; fileName?: string }): Promise<{ syncedFile: unknown | null }>;
|
||||
onedriveDeleteSyncFile?(options: { accessToken: string; fileId: string }): Promise<{ ok: true }>;
|
||||
}
|
||||
}
|
||||
|
||||
export {};
|
||||
152
types/global/netcatty-bridge-system.d.ts
vendored
Normal file
152
types/global/netcatty-bridge-system.d.ts
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
|
||||
declare global {
|
||||
interface NetcattyBridge {
|
||||
probeSystemCapabilities?(sessionId: string): Promise<{
|
||||
success: boolean;
|
||||
pending?: boolean;
|
||||
error?: string;
|
||||
capabilities?: import("../../domain/systemManager/types").SessionCapabilities;
|
||||
}>;
|
||||
listSystemProcesses?(sessionId: string): Promise<{
|
||||
success: boolean;
|
||||
pending?: boolean;
|
||||
error?: string;
|
||||
processes?: import("../../domain/systemManager/types").SystemProcessInfo[];
|
||||
}>;
|
||||
signalSystemProcess?(options: {
|
||||
sessionId: string;
|
||||
pid: number;
|
||||
signal?: string;
|
||||
nice?: number;
|
||||
}): Promise<{ success: boolean; pending?: boolean; error?: string; code?: number }>;
|
||||
setupOsc7Tracking?(sessionId: string, command: string): Promise<{
|
||||
success: boolean;
|
||||
pending?: boolean;
|
||||
stdout?: string;
|
||||
stderr?: string;
|
||||
code?: number | null;
|
||||
error?: string;
|
||||
}>;
|
||||
listTmuxSessions?(sessionId: string): Promise<{
|
||||
success: boolean;
|
||||
error?: string;
|
||||
tmuxVersion?: string;
|
||||
sessions?: import("../../domain/systemManager/types").TmuxSessionInfo[];
|
||||
}>;
|
||||
createTmuxSession?(options: { sessionId: string; name: string; command?: string }): Promise<{
|
||||
success: boolean;
|
||||
error?: string;
|
||||
name?: string;
|
||||
}>;
|
||||
listTmuxWindows?(options: { sessionId: string; sessionName: string }): Promise<{
|
||||
success: boolean;
|
||||
error?: string;
|
||||
debug?: {
|
||||
lastOutput?: string;
|
||||
tried?: string[];
|
||||
sockets?: Array<string | null>;
|
||||
};
|
||||
windows?: import("../../domain/systemManager/types").TmuxWindowInfo[];
|
||||
}>;
|
||||
listTmuxPanes?(options: {
|
||||
sessionId: string;
|
||||
sessionName: string;
|
||||
windowIndex: number;
|
||||
}): Promise<{
|
||||
success: boolean;
|
||||
error?: string;
|
||||
debug?: {
|
||||
lastOutput?: string;
|
||||
tried?: string[];
|
||||
sockets?: Array<string | null>;
|
||||
};
|
||||
panes?: import("../../domain/systemManager/types").TmuxPaneInfo[];
|
||||
}>;
|
||||
listTmuxClients?(options: { sessionId: string; sessionName?: string }): Promise<{
|
||||
success: boolean;
|
||||
error?: string;
|
||||
clients?: import("../../domain/systemManager/types").TmuxClientInfo[];
|
||||
}>;
|
||||
tmuxAction?(options: {
|
||||
sessionId: string;
|
||||
} & import("../../domain/systemManager/types").TmuxManageAction): Promise<{ success: boolean; error?: string }>;
|
||||
listDockerContainers?(sessionId: string): Promise<{
|
||||
success: boolean;
|
||||
error?: string;
|
||||
containers?: import("../../domain/systemManager/types").DockerContainerInfo[];
|
||||
}>;
|
||||
listDockerImages?(sessionId: string): Promise<{
|
||||
success: boolean;
|
||||
error?: string;
|
||||
images?: import("../../domain/systemManager/types").DockerImageInfo[];
|
||||
}>;
|
||||
getDockerStats?(options: { sessionId: string; ids?: string[] }): Promise<{
|
||||
success: boolean;
|
||||
error?: string;
|
||||
stats?: import("../../domain/systemManager/types").DockerStatInfo[];
|
||||
}>;
|
||||
listAccelerators?(sessionId: string): Promise<{
|
||||
success: boolean;
|
||||
pending?: boolean;
|
||||
error?: string;
|
||||
devices?: import("../../domain/systemManager/types").AcceleratorDeviceInfo[];
|
||||
processes?: import("../../domain/systemManager/types").AcceleratorProcessInfo[];
|
||||
nvidiaDriverVersion?: string | null;
|
||||
probedAt?: number;
|
||||
}>;
|
||||
listListeningPorts?(sessionId: string): Promise<{
|
||||
success: boolean;
|
||||
pending?: boolean;
|
||||
error?: string;
|
||||
ports?: import("../../domain/systemManager/types").ListeningPortInfo[];
|
||||
}>;
|
||||
listSystemServices?(sessionId: string): Promise<{
|
||||
success: boolean;
|
||||
pending?: boolean;
|
||||
error?: string;
|
||||
units?: import("../../domain/systemManager/types").SystemdUnitInfo[];
|
||||
}>;
|
||||
systemServiceAction?(options: {
|
||||
sessionId: string;
|
||||
unitName: string;
|
||||
action: import("../../domain/systemManager/types").SystemdUnitAction;
|
||||
scope?: import("../../domain/systemManager/types").SystemdUnitInfo['scope'];
|
||||
}): Promise<{ success: boolean; pending?: boolean; error?: string }>;
|
||||
dockerInspect?(options: { sessionId: string; containerId: string }): Promise<{
|
||||
success: boolean;
|
||||
error?: string;
|
||||
inspect?: Record<string, unknown>;
|
||||
}>;
|
||||
dockerImageInspect?(options: { sessionId: string; imageId: string }): Promise<{
|
||||
success: boolean;
|
||||
error?: string;
|
||||
inspect?: Record<string, unknown>;
|
||||
}>;
|
||||
dockerAction?(options: {
|
||||
sessionId: string;
|
||||
containerId: string;
|
||||
action: import("../../domain/systemManager/types").DockerContainerAction;
|
||||
newName?: string;
|
||||
}): Promise<{ success: boolean; error?: string }>;
|
||||
dockerImageAction?(options: {
|
||||
sessionId: string;
|
||||
} & import("../../domain/systemManager/types").DockerImageManageAction): Promise<{
|
||||
success: boolean;
|
||||
error?: string;
|
||||
output?: string;
|
||||
}>;
|
||||
openTerminalPopup?(payload: import("../../domain/systemManager/types").TerminalPopupPayload): Promise<{
|
||||
success: boolean;
|
||||
error?: string;
|
||||
popupId?: string;
|
||||
}>;
|
||||
logDiagnostic?(payload: {
|
||||
source: string;
|
||||
message: string;
|
||||
extra?: Record<string, unknown>;
|
||||
}): Promise<{ success: boolean; error?: string }>;
|
||||
onTerminalPopupConfig?(cb: (payload: import("../../domain/systemManager/types").TerminalPopupPayload) => void): () => void;
|
||||
}
|
||||
}
|
||||
|
||||
export {};
|
||||
Reference in New Issue
Block a user