mirror of
https://github.com/stablyai/orca.git
synced 2026-09-21 16:02:20 +00:00
* perf(runtime): gate terminal.list visual layouts and stop the false writable claim visualLayouts is ~31% of a large terminal.list payload (44,208 B of 137,412 B on a live 134-terminal remote runtime) and has exactly one consumer: the human-readable CLI formatter. Gate it behind an includeVisualLayouts request param that defaults to included, so pre-flag clients are unaffected, and have every --json/internal caller opt out. Also drop the record-backed builder's writable, which was a verbatim copy of connected. terminal.show now states writability explicitly as exactly what terminal.send's PTY gate enforces. * test(runtime): type the payload-size fixture arrays for tsc * fix(runtime): preserve terminal list compatibility * test(runtime): guard terminal list optimization * fix(cli): preserve agent access to terminal layouts
87 lines
3.3 KiB
TypeScript
87 lines
3.3 KiB
TypeScript
import type { PluginEventName } from '../../shared/plugins/plugin-manifest'
|
|
import { PLUGIN_WORKSPACE_TERMINAL_LIMIT } from '../../shared/plugins/plugin-host-api'
|
|
import type { PluginHostServices } from './plugin-host-methods'
|
|
import { PluginSecretsStore } from './plugin-secrets-store'
|
|
import { PluginKvStore } from './plugin-storage-store'
|
|
|
|
/** Structural subset of OrcaRuntimeService exposed to plugin facade bindings. */
|
|
export type PluginRuntimeDelegate = {
|
|
resolveActiveWorktreeContext(): Promise<{
|
|
worktreeId: string
|
|
path: string
|
|
branch: string
|
|
displayName: string
|
|
} | null>
|
|
listTerminals(
|
|
worktreeSelector?: string,
|
|
limit?: number,
|
|
opts?: { includeVisualLayouts?: boolean }
|
|
): Promise<{ terminals: { handle: string; title: string | null }[] }>
|
|
sendTerminal(
|
|
handle: string,
|
|
action: { text?: string; enter?: boolean }
|
|
): Promise<{ accepted: boolean }>
|
|
dispatchPluginNotification(input: {
|
|
pluginId: string
|
|
title: string
|
|
body?: string
|
|
}): Promise<{ delivered: boolean }>
|
|
}
|
|
|
|
export function bindPluginHostServices(input: {
|
|
delegate: PluginRuntimeDelegate
|
|
pluginsDataDir: string
|
|
subscribeEvents: (pluginKey: string, events: PluginEventName[]) => PluginEventName[]
|
|
}): PluginHostServices {
|
|
const { delegate, pluginsDataDir, subscribeEvents } = input
|
|
return {
|
|
resolveActiveWorktreeContext: async () => {
|
|
const context = await delegate.resolveActiveWorktreeContext()
|
|
if (!context) {
|
|
return null
|
|
}
|
|
// Why: retain the internal id only for host-side terminal membership;
|
|
// the public handler projects it out because it embeds provider paths.
|
|
return {
|
|
worktreeId: context.worktreeId,
|
|
branch: context.branch,
|
|
displayName: context.displayName
|
|
}
|
|
},
|
|
listWorktreeTerminals: async (worktreeId) => {
|
|
const result = await delegate.listTerminals(
|
|
`id:${worktreeId}`,
|
|
PLUGIN_WORKSPACE_TERMINAL_LIMIT,
|
|
{ includeVisualLayouts: false }
|
|
)
|
|
return result.terminals
|
|
.slice(0, PLUGIN_WORKSPACE_TERMINAL_LIMIT)
|
|
.map((terminal) => ({ id: terminal.handle }))
|
|
},
|
|
sendTerminalText: async (terminalId, action) => {
|
|
const result = await delegate.sendTerminal(terminalId, action)
|
|
return { accepted: result.accepted }
|
|
},
|
|
dispatchPluginNotification: (notification) => delegate.dispatchPluginNotification(notification),
|
|
storage: {
|
|
get: (key, itemKey) => new PluginKvStore(pluginsDataDir, key, 'storage.json').get(itemKey),
|
|
set: (key, itemKey, value) =>
|
|
new PluginKvStore(pluginsDataDir, key, 'storage.json').set(itemKey, value),
|
|
delete: (key, itemKey) =>
|
|
new PluginKvStore(pluginsDataDir, key, 'storage.json').delete(itemKey),
|
|
keys: (key) => new PluginKvStore(pluginsDataDir, key, 'storage.json').keys()
|
|
},
|
|
secrets: {
|
|
get: (key, itemKey) => new PluginSecretsStore(pluginsDataDir, key).get(itemKey),
|
|
set: (key, itemKey, value) => new PluginSecretsStore(pluginsDataDir, key).set(itemKey, value),
|
|
delete: (key, itemKey) => new PluginSecretsStore(pluginsDataDir, key).delete(itemKey)
|
|
},
|
|
settings: {
|
|
getAll: (key) => new PluginKvStore(pluginsDataDir, key, 'settings.json').getAll(),
|
|
set: (key, itemKey, value) =>
|
|
new PluginKvStore(pluginsDataDir, key, 'settings.json').set(itemKey, value)
|
|
},
|
|
subscribeEvents
|
|
}
|
|
}
|