need dist for plugins

Signed-off-by: Dmytro Stanchiev <git@dmytros.dev>
This commit is contained in:
2026-04-19 19:15:51 -04:00
parent 25291b2ba4
commit 15be750b5c
55 changed files with 29302 additions and 1 deletions

View File

@@ -0,0 +1,21 @@
import type { TmuxConfig } from "../../config/schema";
import type { applyLayout, closeTmuxPane, enforceMainPaneWidth, replaceTmuxPane, spawnTmuxPane } from "../../shared/tmux";
import type { PaneAction, WindowState } from "./types";
export interface ActionResult {
success: boolean;
paneId?: string;
error?: string;
}
export interface ExecuteContext {
config: TmuxConfig;
serverUrl: string;
windowState: WindowState;
}
export interface ActionExecutorDeps {
spawnTmuxPane: typeof spawnTmuxPane;
closeTmuxPane: typeof closeTmuxPane;
replaceTmuxPane: typeof replaceTmuxPane;
applyLayout: typeof applyLayout;
enforceMainPaneWidth: typeof enforceMainPaneWidth;
}
export declare function executeActionWithDeps(action: PaneAction, ctx: ExecuteContext, deps: ActionExecutorDeps): Promise<ActionResult>;

View File

@@ -0,0 +1,20 @@
import type { TmuxConfig } from "../../config/schema";
import type { PaneAction, WindowState } from "./types";
import type { ActionResult } from "./action-executor-core";
export type { ActionExecutorDeps, ActionResult } from "./action-executor-core";
export interface ExecuteActionsResult {
success: boolean;
spawnedPaneId?: string;
results: Array<{
action: PaneAction;
result: ActionResult;
}>;
}
export interface ExecuteContext {
config: TmuxConfig;
serverUrl: string;
windowState: WindowState;
sourcePaneId?: string;
}
export declare function executeAction(action: PaneAction, ctx: ExecuteContext): Promise<ActionResult>;
export declare function executeActions(actions: PaneAction[], ctx: ExecuteContext): Promise<ExecuteActionsResult>;

View File

@@ -0,0 +1,9 @@
import type { TmuxConfig } from "../../config/schema";
import type { TrackedSession } from "./types";
export declare function cleanupTmuxSessions(params: {
tmuxConfig: TmuxConfig;
serverUrl: string;
sourcePaneId: string | undefined;
sessions: Map<string, TrackedSession>;
stopPolling: () => void;
}): Promise<void>;

View File

@@ -0,0 +1,7 @@
export type { SessionMapping } from "./oldest-agent-pane";
export type { GridCapacity, GridPlan, GridSlot } from "./grid-planning";
export type { SpawnTarget } from "./spawn-target-finder";
export { calculateCapacity, computeGridPlan, mapPaneToSlot, } from "./grid-planning";
export { canSplitPane, canSplitPaneAnyDirection, findMinimalEvictions, getBestSplitDirection, getColumnCount, getColumnWidth, isSplittableAtCount, } from "./pane-split-availability";
export { findSpawnTarget } from "./spawn-target-finder";
export { decideCloseAction, decideSpawnActions } from "./spawn-action-decider";

View File

@@ -0,0 +1,6 @@
export { coerceSessionCreatedEvent } from "./session-created-event";
export type { SessionCreatedEvent } from "./session-created-event";
export { handleSessionCreated } from "./session-created-handler";
export type { SessionCreatedHandlerDeps } from "./session-created-handler";
export { handleSessionDeleted } from "./session-deleted-handler";
export type { SessionDeletedHandlerDeps } from "./session-deleted-handler";

View File

@@ -0,0 +1,21 @@
import type { CapacityConfig, TmuxPaneInfo } from "./types";
export interface GridCapacity {
cols: number;
rows: number;
total: number;
}
export interface GridSlot {
row: number;
col: number;
}
export interface GridPlan {
cols: number;
rows: number;
slotWidth: number;
slotHeight: number;
}
type CapacityOptions = CapacityConfig | number | undefined;
export declare function calculateCapacity(windowWidth: number, windowHeight: number, options?: CapacityOptions, mainPaneWidth?: number): GridCapacity;
export declare function computeGridPlan(windowWidth: number, windowHeight: number, paneCount: number, options?: CapacityOptions, mainPaneWidth?: number): GridPlan;
export declare function mapPaneToSlot(pane: TmuxPaneInfo, plan: GridPlan, mainPaneWidth: number): GridSlot;
export {};

16
dist/features/tmux-subagent/index.d.ts vendored Normal file
View File

@@ -0,0 +1,16 @@
export * from "./manager";
export * from "./event-handlers";
export * from "./polling";
export * from "./cleanup";
export * from "./session-created-event";
export * from "./session-created-handler";
export * from "./session-deleted-handler";
export * from "./polling-constants";
export * from "./session-status-parser";
export * from "./session-message-count";
export * from "./session-ready-waiter";
export * from "./types";
export * from "./pane-state-parser";
export * from "./pane-state-querier";
export * from "./decision-engine";
export * from "./action-executor";

View File

@@ -0,0 +1,61 @@
import type { PluginInput } from "@opencode-ai/plugin";
import type { TmuxConfig } from "../../config/schema";
interface SessionCreatedEvent {
type: string;
properties?: {
info?: {
id?: string;
parentID?: string;
title?: string;
};
};
}
export interface TmuxUtilDeps {
isInsideTmux: () => boolean;
getCurrentPaneId: () => string | undefined;
}
export declare class TmuxSessionManager {
private client;
private tmuxConfig;
private serverUrl;
private sourcePaneId;
private sessions;
private pendingSessions;
private spawnQueue;
private deferredSessions;
private deferredQueue;
private deferredAttachInterval?;
private deferredAttachTickScheduled;
private nullStateCount;
private deps;
private pollingManager;
constructor(ctx: PluginInput, tmuxConfig: TmuxConfig, deps?: TmuxUtilDeps);
private isEnabled;
private getCapacityConfig;
private getSessionMappings;
private removeTrackedSession;
private markSessionClosePending;
private queryWindowStateSafely;
private tryCloseTrackedSession;
private retryPendingCloses;
private enqueueDeferredSession;
private removeDeferredSession;
private startDeferredAttachLoop;
private stopDeferredAttachLoop;
private tryAttachDeferredSession;
private waitForSessionReady;
onSessionCreated(event: SessionCreatedEvent): Promise<void>;
private enqueueSpawn;
onSessionDeleted(event: {
sessionID: string;
}): Promise<void>;
private closeSessionById;
createEventHandler(): (input: {
event: {
type: string;
properties?: unknown;
};
}) => Promise<void>;
cleanup(): Promise<void>;
}
export {};

View File

@@ -0,0 +1,7 @@
import type { TmuxPaneInfo } from "./types";
export interface SessionMapping {
sessionId: string;
paneId: string;
createdAt: Date;
}
export declare function findOldestAgentPane(agentPanes: TmuxPaneInfo[], sessionMappings: SessionMapping[]): TmuxPaneInfo | null;

View File

@@ -0,0 +1,8 @@
import type { SplitDirection, TmuxPaneInfo } from "./types";
export declare function getColumnCount(paneCount: number): number;
export declare function getColumnWidth(agentAreaWidth: number, paneCount: number): number;
export declare function isSplittableAtCount(agentAreaWidth: number, paneCount: number, minPaneWidth?: number): boolean;
export declare function findMinimalEvictions(agentAreaWidth: number, currentCount: number, minPaneWidth?: number): number | null;
export declare function canSplitPane(pane: TmuxPaneInfo, direction: SplitDirection, minPaneWidth?: number): boolean;
export declare function canSplitPaneAnyDirection(pane: TmuxPaneInfo, minPaneWidth?: number): boolean;
export declare function getBestSplitDirection(pane: TmuxPaneInfo, minPaneWidth?: number): SplitDirection | null;

View File

@@ -0,0 +1,8 @@
import type { TmuxPaneInfo } from "./types";
type ParsedPaneState = {
windowWidth: number;
windowHeight: number;
panes: TmuxPaneInfo[];
};
export declare function parsePaneStateOutput(stdout: string): ParsedPaneState | null;
export {};

View File

@@ -0,0 +1,2 @@
import type { WindowState } from "./types";
export declare function queryWindowState(sourcePaneId: string): Promise<WindowState | null>;

View File

@@ -0,0 +1,3 @@
export declare const SESSION_TIMEOUT_MS: number;
export declare const MIN_STABILITY_TIME_MS: number;
export declare const STABLE_POLLS_REQUIRED = 3;

View File

@@ -0,0 +1,15 @@
import type { PluginInput } from "@opencode-ai/plugin";
import type { TrackedSession } from "./types";
type OpencodeClient = PluginInput["client"];
export declare class TmuxPollingManager {
private client;
private sessions;
private closeSessionById;
private pollInterval?;
private pollingInFlight;
constructor(client: OpencodeClient, sessions: Map<string, TrackedSession>, closeSessionById: (sessionId: string) => Promise<void>);
startPolling(): void;
stopPolling(): void;
private pollSessions;
}
export {};

View File

@@ -0,0 +1,19 @@
import type { PluginInput } from "@opencode-ai/plugin";
import type { TmuxConfig } from "../../config/schema";
import type { TrackedSession } from "./types";
type OpencodeClient = PluginInput["client"];
export interface SessionPollingController {
startPolling: () => void;
stopPolling: () => void;
closeSessionById: (sessionId: string) => Promise<void>;
waitForSessionReady: (sessionId: string) => Promise<boolean>;
pollSessions: () => Promise<void>;
}
export declare function createSessionPollingController(params: {
client: OpencodeClient;
tmuxConfig: TmuxConfig;
serverUrl: string;
sourcePaneId: string | undefined;
sessions: Map<string, TrackedSession>;
}): SessionPollingController;
export {};

View File

@@ -0,0 +1,14 @@
export interface SessionCreatedEvent {
type: string;
properties?: {
info?: {
id?: string;
parentID?: string;
title?: string;
};
};
}
export declare function coerceSessionCreatedEvent(input: {
type: string;
properties?: unknown;
}): SessionCreatedEvent;

View File

@@ -0,0 +1,22 @@
import type { PluginInput } from "@opencode-ai/plugin";
import type { TmuxConfig } from "../../config/schema";
import type { CapacityConfig, TrackedSession } from "./types";
import { type SessionMapping } from "./decision-engine";
import type { SessionCreatedEvent } from "./session-created-event";
type OpencodeClient = PluginInput["client"];
export interface SessionCreatedHandlerDeps {
client: OpencodeClient;
tmuxConfig: TmuxConfig;
serverUrl: string;
sourcePaneId: string | undefined;
sessions: Map<string, TrackedSession>;
pendingSessions: Set<string>;
isInsideTmux: () => boolean;
isEnabled: () => boolean;
getCapacityConfig: () => CapacityConfig;
getSessionMappings: () => SessionMapping[];
waitForSessionReady: (sessionId: string) => Promise<boolean>;
startPolling: () => void;
}
export declare function handleSessionCreated(deps: SessionCreatedHandlerDeps, event: SessionCreatedEvent): Promise<void>;
export {};

View File

@@ -0,0 +1,15 @@
import type { TmuxConfig } from "../../config/schema";
import type { TrackedSession } from "./types";
import { type SessionMapping } from "./decision-engine";
export interface SessionDeletedHandlerDeps {
tmuxConfig: TmuxConfig;
serverUrl: string;
sourcePaneId: string | undefined;
sessions: Map<string, TrackedSession>;
isEnabled: () => boolean;
getSessionMappings: () => SessionMapping[];
stopPolling: () => void;
}
export declare function handleSessionDeleted(deps: SessionDeletedHandlerDeps, event: {
sessionID: string;
}): Promise<void>;

View File

@@ -0,0 +1 @@
export declare function getMessageCount(data: unknown): number;

View File

@@ -0,0 +1,7 @@
import type { PluginInput } from "@opencode-ai/plugin";
type OpencodeClient = PluginInput["client"];
export declare function waitForSessionReady(params: {
client: OpencodeClient;
sessionId: string;
}): Promise<boolean>;
export {};

View File

@@ -0,0 +1,5 @@
type SessionStatus = {
type: string;
};
export declare function parseSessionStatusMap(data: unknown): Record<string, SessionStatus>;
export {};

View File

@@ -0,0 +1,4 @@
import type { CapacityConfig, PaneAction, SpawnDecision, WindowState } from "./types";
import { type SessionMapping } from "./oldest-agent-pane";
export declare function decideSpawnActions(state: WindowState, sessionId: string, description: string, config: CapacityConfig, sessionMappings: SessionMapping[]): SpawnDecision;
export declare function decideCloseAction(state: WindowState, sessionId: string, sessionMappings: SessionMapping[]): PaneAction | null;

View File

@@ -0,0 +1,6 @@
import type { CapacityConfig, SplitDirection, WindowState } from "./types";
export interface SpawnTarget {
targetPaneId: string;
splitDirection: SplitDirection;
}
export declare function findSpawnTarget(state: WindowState, config: CapacityConfig): SpawnTarget | null;

View File

@@ -0,0 +1,11 @@
import type { CapacityConfig } from "./types";
export declare const MAIN_PANE_RATIO = 0.5;
export declare const MAX_COLS = 2;
export declare const MAX_ROWS = 3;
export declare const MAX_GRID_SIZE = 4;
export declare const DIVIDER_SIZE = 1;
export declare const MIN_SPLIT_WIDTH: number;
export declare const MIN_SPLIT_HEIGHT: number;
export declare function getMainPaneSizePercent(config?: CapacityConfig): number;
export declare function computeMainPaneWidth(windowWidth: number, config?: CapacityConfig): number;
export declare function computeAgentAreaWidth(windowWidth: number, config?: CapacityConfig): number;

View File

@@ -0,0 +1,8 @@
import type { TrackedSession } from "./types";
export declare function createTrackedSession(params: {
sessionId: string;
paneId: string;
description: string;
now?: Date;
}): TrackedSession;
export declare function markTrackedSessionClosePending(tracked: TrackedSession): TrackedSession;

57
dist/features/tmux-subagent/types.d.ts vendored Normal file
View File

@@ -0,0 +1,57 @@
export interface TrackedSession {
sessionId: string;
paneId: string;
description: string;
createdAt: Date;
lastSeenAt: Date;
closePending: boolean;
closeRetryCount: number;
lastMessageCount?: number;
stableIdlePolls?: number;
}
export declare const MIN_PANE_WIDTH = 52;
export declare const MIN_PANE_HEIGHT = 11;
export interface TmuxPaneInfo {
paneId: string;
width: number;
height: number;
left: number;
top: number;
title: string;
isActive: boolean;
}
export interface WindowState {
windowWidth: number;
windowHeight: number;
mainPane: TmuxPaneInfo | null;
agentPanes: TmuxPaneInfo[];
}
export type SplitDirection = "-h" | "-v";
export type PaneAction = {
type: "close";
paneId: string;
sessionId: string;
} | {
type: "spawn";
sessionId: string;
description: string;
targetPaneId: string;
splitDirection: SplitDirection;
} | {
type: "replace";
paneId: string;
oldSessionId: string;
newSessionId: string;
description: string;
};
export interface SpawnDecision {
canSpawn: boolean;
actions: PaneAction[];
reason?: string;
}
export interface CapacityConfig {
layout?: string;
mainPaneSize?: number;
mainPaneMinWidth: number;
agentPaneWidth: number;
}