refactor: wave 1 - extract leaf modules, rename catch-all files, split index.ts hooks

- Split 25+ index.ts files into hook.ts + extracted modules
- Rename all catch-all utils.ts/helpers.ts to domain-specific names
- Split src/tools/lsp/ into ~15 focused modules
- Split src/tools/delegate-task/ into ~18 focused modules
- Separate shared types from implementation
- 155 files changed, 60+ new files created
- All typecheck clean, 61 tests pass
This commit is contained in:
YeonGyu-Kim
2026-02-08 13:57:26 +09:00
parent 7a15c1f3f9
commit df03300211
156 changed files with 7280 additions and 6771 deletions
@@ -1,6 +1,6 @@
import { spawn } from "bun"
import type { WindowState, TmuxPaneInfo } from "./types"
import { getTmuxPath } from "../../tools/interactive-bash/utils"
import { getTmuxPath } from "../../tools/interactive-bash/tmux-path-resolver"
import { log } from "../../shared"
export async function queryWindowState(sourcePaneId: string): Promise<WindowState | null> {
+7 -84
View File
@@ -1,84 +1,7 @@
/**
* Pending tool metadata store.
*
* OpenCode's `fromPlugin()` wrapper always replaces the metadata returned by
* plugin tools with `{ truncated, outputPath }`, discarding any sessionId,
* title, or custom metadata set during `execute()`.
*
* This store captures metadata written via `ctx.metadata()` inside execute(),
* then the `tool.execute.after` hook consumes it and merges it back into the
* result *before* the processor writes the final part to the session store.
*
* Flow:
* execute() → storeToolMetadata(sessionID, callID, data)
* fromPlugin() → overwrites metadata with { truncated }
* tool.execute.after → consumeToolMetadata(sessionID, callID) → merges back
* processor → Session.updatePart(status:"completed", metadata: result.metadata)
*/
export interface PendingToolMetadata {
title?: string
metadata?: Record<string, unknown>
}
const pendingStore = new Map<string, PendingToolMetadata & { storedAt: number }>()
const STALE_TIMEOUT_MS = 15 * 60 * 1000
function makeKey(sessionID: string, callID: string): string {
return `${sessionID}:${callID}`
}
function cleanupStaleEntries(): void {
const now = Date.now()
for (const [key, entry] of pendingStore) {
if (now - entry.storedAt > STALE_TIMEOUT_MS) {
pendingStore.delete(key)
}
}
}
/**
* Store metadata to be restored after fromPlugin() overwrites it.
* Called from tool execute() functions alongside ctx.metadata().
*/
export function storeToolMetadata(
sessionID: string,
callID: string,
data: PendingToolMetadata,
): void {
cleanupStaleEntries()
pendingStore.set(makeKey(sessionID, callID), { ...data, storedAt: Date.now() })
}
/**
* Consume stored metadata (one-time read, removes from store).
* Called from tool.execute.after hook.
*/
export function consumeToolMetadata(
sessionID: string,
callID: string,
): PendingToolMetadata | undefined {
const key = makeKey(sessionID, callID)
const stored = pendingStore.get(key)
if (stored) {
pendingStore.delete(key)
const { storedAt: _, ...data } = stored
return data
}
return undefined
}
/**
* Get current store size (for testing/debugging).
*/
export function getPendingStoreSize(): number {
return pendingStore.size
}
/**
* Clear all pending metadata (for testing).
*/
export function clearPendingStore(): void {
pendingStore.clear()
}
export {
clearPendingStore,
consumeToolMetadata,
getPendingStoreSize,
storeToolMetadata,
} from "./store"
export type { PendingToolMetadata } from "./store"
+84
View File
@@ -0,0 +1,84 @@
/**
* Pending tool metadata store.
*
* OpenCode's `fromPlugin()` wrapper always replaces the metadata returned by
* plugin tools with `{ truncated, outputPath }`, discarding any sessionId,
* title, or custom metadata set during `execute()`.
*
* This store captures metadata written via `ctx.metadata()` inside execute(),
* then the `tool.execute.after` hook consumes it and merges it back into the
* result *before* the processor writes the final part to the session store.
*
* Flow:
* execute() → storeToolMetadata(sessionID, callID, data)
* fromPlugin() → overwrites metadata with { truncated }
* tool.execute.after → consumeToolMetadata(sessionID, callID) → merges back
* processor → Session.updatePart(status:"completed", metadata: result.metadata)
*/
export interface PendingToolMetadata {
title?: string
metadata?: Record<string, unknown>
}
const pendingStore = new Map<string, PendingToolMetadata & { storedAt: number }>()
const STALE_TIMEOUT_MS = 15 * 60 * 1000
function makeKey(sessionID: string, callID: string): string {
return `${sessionID}:${callID}`
}
function cleanupStaleEntries(): void {
const now = Date.now()
for (const [key, entry] of pendingStore) {
if (now - entry.storedAt > STALE_TIMEOUT_MS) {
pendingStore.delete(key)
}
}
}
/**
* Store metadata to be restored after fromPlugin() overwrites it.
* Called from tool execute() functions alongside ctx.metadata().
*/
export function storeToolMetadata(
sessionID: string,
callID: string,
data: PendingToolMetadata
): void {
cleanupStaleEntries()
pendingStore.set(makeKey(sessionID, callID), { ...data, storedAt: Date.now() })
}
/**
* Consume stored metadata (one-time read, removes from store).
* Called from tool.execute.after hook.
*/
export function consumeToolMetadata(
sessionID: string,
callID: string
): PendingToolMetadata | undefined {
const key = makeKey(sessionID, callID)
const stored = pendingStore.get(key)
if (stored) {
pendingStore.delete(key)
const { storedAt: _, ...data } = stored
return data
}
return undefined
}
/**
* Get current store size (for testing/debugging).
*/
export function getPendingStoreSize(): number {
return pendingStore.size
}
/**
* Clear all pending metadata (for testing).
*/
export function clearPendingStore(): void {
pendingStore.clear()
}