@agentuity/opencode 0.1.39 → 0.1.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +321 -9
- package/dist/agents/architect.d.ts +4 -0
- package/dist/agents/architect.d.ts.map +1 -0
- package/dist/agents/architect.js +259 -0
- package/dist/agents/architect.js.map +1 -0
- package/dist/agents/builder.d.ts +1 -1
- package/dist/agents/builder.d.ts.map +1 -1
- package/dist/agents/builder.js +44 -1
- package/dist/agents/builder.js.map +1 -1
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js +6 -0
- package/dist/agents/index.js.map +1 -1
- package/dist/agents/lead.d.ts +1 -1
- package/dist/agents/lead.d.ts.map +1 -1
- package/dist/agents/lead.js +183 -19
- package/dist/agents/lead.js.map +1 -1
- package/dist/agents/planner.d.ts +4 -0
- package/dist/agents/planner.d.ts.map +1 -0
- package/dist/agents/planner.js +158 -0
- package/dist/agents/planner.js.map +1 -0
- package/dist/agents/runner.d.ts +4 -0
- package/dist/agents/runner.d.ts.map +1 -0
- package/dist/agents/runner.js +364 -0
- package/dist/agents/runner.js.map +1 -0
- package/dist/agents/types.d.ts +5 -1
- package/dist/agents/types.d.ts.map +1 -1
- package/dist/background/concurrency.d.ts +36 -0
- package/dist/background/concurrency.d.ts.map +1 -0
- package/dist/background/concurrency.js +92 -0
- package/dist/background/concurrency.js.map +1 -0
- package/dist/background/index.d.ts +5 -0
- package/dist/background/index.d.ts.map +1 -0
- package/dist/background/index.js +4 -0
- package/dist/background/index.js.map +1 -0
- package/dist/background/manager.d.ts +54 -0
- package/dist/background/manager.d.ts.map +1 -0
- package/dist/background/manager.js +409 -0
- package/dist/background/manager.js.map +1 -0
- package/dist/background/types.d.ts +47 -0
- package/dist/background/types.d.ts.map +1 -0
- package/dist/background/types.js +2 -0
- package/dist/background/types.js.map +1 -0
- package/dist/config/index.d.ts +2 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +2 -0
- package/dist/config/index.js.map +1 -1
- package/dist/config/loader.d.ts +24 -0
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +102 -23
- package/dist/config/loader.js.map +1 -1
- package/dist/config/presets.d.ts +16 -0
- package/dist/config/presets.d.ts.map +1 -0
- package/dist/config/presets.js +20 -0
- package/dist/config/presets.js.map +1 -0
- package/dist/config/validation.d.ts +26 -0
- package/dist/config/validation.d.ts.map +1 -0
- package/dist/config/validation.js +48 -0
- package/dist/config/validation.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/plugin/hooks/keyword.d.ts.map +1 -1
- package/dist/plugin/hooks/keyword.js +3 -0
- package/dist/plugin/hooks/keyword.js.map +1 -1
- package/dist/plugin/plugin.d.ts.map +1 -1
- package/dist/plugin/plugin.js +297 -36
- package/dist/plugin/plugin.js.map +1 -1
- package/dist/skills/frontmatter.d.ts +7 -0
- package/dist/skills/frontmatter.d.ts.map +1 -0
- package/dist/skills/frontmatter.js +17 -0
- package/dist/skills/frontmatter.js.map +1 -0
- package/dist/skills/index.d.ts +4 -0
- package/dist/skills/index.d.ts.map +1 -0
- package/dist/skills/index.js +4 -0
- package/dist/skills/index.js.map +1 -0
- package/dist/skills/loader.d.ts +20 -0
- package/dist/skills/loader.d.ts.map +1 -0
- package/dist/skills/loader.js +152 -0
- package/dist/skills/loader.js.map +1 -0
- package/dist/skills/types.d.ts +41 -0
- package/dist/skills/types.d.ts.map +1 -0
- package/dist/skills/types.js +2 -0
- package/dist/skills/types.js.map +1 -0
- package/dist/tmux/decision-engine.d.ts +24 -0
- package/dist/tmux/decision-engine.d.ts.map +1 -0
- package/dist/tmux/decision-engine.js +193 -0
- package/dist/tmux/decision-engine.js.map +1 -0
- package/dist/tmux/executor.d.ts +56 -0
- package/dist/tmux/executor.d.ts.map +1 -0
- package/dist/tmux/executor.js +231 -0
- package/dist/tmux/executor.js.map +1 -0
- package/dist/tmux/index.d.ts +7 -0
- package/dist/tmux/index.d.ts.map +1 -0
- package/dist/tmux/index.js +7 -0
- package/dist/tmux/index.js.map +1 -0
- package/dist/tmux/manager.d.ts +80 -0
- package/dist/tmux/manager.d.ts.map +1 -0
- package/dist/tmux/manager.js +276 -0
- package/dist/tmux/manager.js.map +1 -0
- package/dist/tmux/state-query.d.ts +7 -0
- package/dist/tmux/state-query.d.ts.map +1 -0
- package/dist/tmux/state-query.js +67 -0
- package/dist/tmux/state-query.js.map +1 -0
- package/dist/tmux/types.d.ts +96 -0
- package/dist/tmux/types.d.ts.map +1 -0
- package/dist/tmux/types.js +8 -0
- package/dist/tmux/types.js.map +1 -0
- package/dist/tmux/utils.d.ts +32 -0
- package/dist/tmux/utils.d.ts.map +1 -0
- package/dist/tmux/utils.js +80 -0
- package/dist/tmux/utils.js.map +1 -0
- package/dist/tools/background.d.ts +61 -0
- package/dist/tools/background.d.ts.map +1 -0
- package/dist/tools/background.js +78 -0
- package/dist/tools/background.js.map +1 -0
- package/dist/tools/delegate.d.ts +6 -0
- package/dist/tools/delegate.d.ts.map +1 -1
- package/dist/tools/delegate.js +8 -2
- package/dist/tools/delegate.js.map +1 -1
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +1 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/types.d.ts +118 -18
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +49 -7
- package/dist/types.js.map +1 -1
- package/package.json +4 -3
- package/src/agents/architect.ts +262 -0
- package/src/agents/builder.ts +44 -1
- package/src/agents/index.ts +6 -0
- package/src/agents/lead.ts +183 -19
- package/src/agents/planner.ts +161 -0
- package/src/agents/runner.ts +367 -0
- package/src/agents/types.ts +5 -1
- package/src/background/concurrency.ts +116 -0
- package/src/background/index.ts +4 -0
- package/src/background/manager.ts +478 -0
- package/src/background/types.ts +52 -0
- package/src/config/index.ts +2 -0
- package/src/config/loader.ts +128 -31
- package/src/config/presets.ts +21 -0
- package/src/config/validation.ts +70 -0
- package/src/index.ts +1 -0
- package/src/plugin/hooks/keyword.ts +3 -0
- package/src/plugin/plugin.ts +323 -42
- package/src/skills/frontmatter.ts +25 -0
- package/src/skills/index.ts +3 -0
- package/src/skills/loader.ts +185 -0
- package/src/skills/types.ts +43 -0
- package/src/tmux/decision-engine.ts +246 -0
- package/src/tmux/executor.ts +286 -0
- package/src/tmux/index.ts +11 -0
- package/src/tmux/manager.ts +331 -0
- package/src/tmux/state-query.ts +74 -0
- package/src/tmux/types.ts +106 -0
- package/src/tmux/utils.ts +85 -0
- package/src/tools/background.ts +145 -0
- package/src/tools/delegate.ts +8 -2
- package/src/tools/index.ts +9 -0
- package/src/types.ts +88 -15
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import { runTmuxCommand, runTmuxCommandSync } from './utils';
|
|
2
|
+
/**
|
|
3
|
+
* Escape a string for safe use in shell commands.
|
|
4
|
+
* Wraps in single quotes and escapes any internal single quotes.
|
|
5
|
+
*/
|
|
6
|
+
function shellEscape(str) {
|
|
7
|
+
// Replace single quotes with '\'' (end quote, escaped quote, start quote)
|
|
8
|
+
return `'${str.replace(/'/g, "'\\''")}'`;
|
|
9
|
+
}
|
|
10
|
+
/** Maximum retries for recursive spawn attempts to prevent infinite loops */
|
|
11
|
+
const MAX_SPAWN_RETRIES = 3;
|
|
12
|
+
/**
|
|
13
|
+
* State for separate-window mode - tracks the dedicated "Agents" window
|
|
14
|
+
*/
|
|
15
|
+
let agentsWindowId;
|
|
16
|
+
/**
|
|
17
|
+
* Execute a single pane action
|
|
18
|
+
*
|
|
19
|
+
* All agents spawn in a dedicated "Agents" window with tiled grid layout.
|
|
20
|
+
*/
|
|
21
|
+
export async function executeAction(action, ctx) {
|
|
22
|
+
switch (action.type) {
|
|
23
|
+
case 'spawn':
|
|
24
|
+
return spawnInAgentsWindow(action, { serverUrl: ctx.serverUrl });
|
|
25
|
+
case 'close':
|
|
26
|
+
return closePane(action);
|
|
27
|
+
case 'replace':
|
|
28
|
+
return replacePane(action, ctx);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Execute multiple actions in sequence
|
|
33
|
+
*/
|
|
34
|
+
export async function executeActions(actions, ctx) {
|
|
35
|
+
const results = [];
|
|
36
|
+
let spawnedPaneId;
|
|
37
|
+
for (const action of actions) {
|
|
38
|
+
const result = await executeAction(action, ctx);
|
|
39
|
+
results.push({ action, result });
|
|
40
|
+
if (!result.success) {
|
|
41
|
+
return { success: false, spawnedPaneId, results };
|
|
42
|
+
}
|
|
43
|
+
if (action.type === 'spawn' && result.paneId) {
|
|
44
|
+
spawnedPaneId = result.paneId;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return { success: true, spawnedPaneId, results };
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Close an existing pane
|
|
51
|
+
* Uses: tmux kill-pane -t <paneId>
|
|
52
|
+
*/
|
|
53
|
+
async function closePane(action) {
|
|
54
|
+
const result = await runTmuxCommand(['kill-pane', '-t', action.paneId]);
|
|
55
|
+
if (!result.success) {
|
|
56
|
+
return { success: false, error: result.output };
|
|
57
|
+
}
|
|
58
|
+
return { success: true };
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Close a pane by its ID
|
|
62
|
+
* Exported for use by TmuxSessionManager when sessions complete
|
|
63
|
+
*/
|
|
64
|
+
export async function closePaneById(paneId) {
|
|
65
|
+
const result = await runTmuxCommand(['kill-pane', '-t', paneId]);
|
|
66
|
+
if (!result.success) {
|
|
67
|
+
return { success: false, error: result.output };
|
|
68
|
+
}
|
|
69
|
+
return { success: true };
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Replace an existing pane with a new session
|
|
73
|
+
* Pane self-destructs when command exits (session complete, server died, etc.)
|
|
74
|
+
*/
|
|
75
|
+
async function replacePane(action, ctx) {
|
|
76
|
+
// Pane kills itself when opencode attach exits (for any reason)
|
|
77
|
+
// Use shellEscape to prevent shell injection via session IDs
|
|
78
|
+
const escapedServerUrl = shellEscape(ctx.serverUrl);
|
|
79
|
+
const escapedSessionId = shellEscape(action.newSessionId);
|
|
80
|
+
const command = `opencode attach ${escapedServerUrl} --session ${escapedSessionId}; tmux kill-pane`;
|
|
81
|
+
const result = await runTmuxCommand(['respawn-pane', '-k', '-t', action.paneId, command]);
|
|
82
|
+
if (!result.success) {
|
|
83
|
+
return { success: false, error: result.output };
|
|
84
|
+
}
|
|
85
|
+
return { success: true, paneId: action.paneId };
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Spawn agent in a dedicated "Agents" window with tiled grid layout
|
|
89
|
+
*
|
|
90
|
+
* On first spawn: Creates a new window named "Agents"
|
|
91
|
+
* Subsequent spawns: Splits within that window
|
|
92
|
+
* After each spawn: Applies tiled layout for a clean grid
|
|
93
|
+
*
|
|
94
|
+
* This keeps the main pane untouched while grouping all agent panes together.
|
|
95
|
+
* Tip: Click a pane to select it, then press Ctrl-b z to zoom/unzoom.
|
|
96
|
+
*
|
|
97
|
+
* @param retryCount - Internal counter to prevent infinite recursion (default 0)
|
|
98
|
+
*/
|
|
99
|
+
async function spawnInAgentsWindow(action, ctx, retryCount = 0) {
|
|
100
|
+
// Prevent infinite recursion if tmux keeps failing
|
|
101
|
+
if (retryCount >= MAX_SPAWN_RETRIES) {
|
|
102
|
+
return {
|
|
103
|
+
success: false,
|
|
104
|
+
error: `Failed to spawn agent pane after ${MAX_SPAWN_RETRIES} attempts`,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
// Pane kills itself when opencode attach exits (session complete, server died, etc.)
|
|
108
|
+
// Use shellEscape to prevent shell injection via session IDs
|
|
109
|
+
const escapedServerUrl = shellEscape(ctx.serverUrl);
|
|
110
|
+
const escapedSessionId = shellEscape(action.sessionId);
|
|
111
|
+
const command = `opencode attach ${escapedServerUrl} --session ${escapedSessionId}; tmux kill-pane`;
|
|
112
|
+
const layout = 'tiled'; // Always use tiled layout for grid arrangement
|
|
113
|
+
// Check if we have a cached agents window ID and if it still exists
|
|
114
|
+
if (agentsWindowId) {
|
|
115
|
+
const checkResult = await runTmuxCommand([
|
|
116
|
+
'list-panes',
|
|
117
|
+
'-t',
|
|
118
|
+
agentsWindowId,
|
|
119
|
+
'-F',
|
|
120
|
+
'#{pane_id}',
|
|
121
|
+
]);
|
|
122
|
+
if (!checkResult.success) {
|
|
123
|
+
// Window no longer exists, clear the cache
|
|
124
|
+
agentsWindowId = undefined;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// If no agents window exists, create one
|
|
128
|
+
if (!agentsWindowId) {
|
|
129
|
+
const createResult = await runTmuxCommand([
|
|
130
|
+
'new-window',
|
|
131
|
+
'-d', // Don't switch to new window
|
|
132
|
+
'-P',
|
|
133
|
+
'-F',
|
|
134
|
+
'#{window_id}:#{pane_id}',
|
|
135
|
+
'-n',
|
|
136
|
+
'Agents',
|
|
137
|
+
command,
|
|
138
|
+
]);
|
|
139
|
+
if (!createResult.success) {
|
|
140
|
+
return { success: false, error: createResult.output };
|
|
141
|
+
}
|
|
142
|
+
// Parse window_id:pane_id from output
|
|
143
|
+
const output = createResult.output?.trim() || '';
|
|
144
|
+
const [windowId, paneId] = output.split(':');
|
|
145
|
+
agentsWindowId = windowId;
|
|
146
|
+
// Apply initial layout (useful when more panes are added later)
|
|
147
|
+
if (agentsWindowId && layout) {
|
|
148
|
+
await runTmuxCommand(['select-layout', '-t', agentsWindowId, layout]);
|
|
149
|
+
}
|
|
150
|
+
return { success: true, paneId, windowId };
|
|
151
|
+
}
|
|
152
|
+
// Agents window exists - split within it
|
|
153
|
+
// First, get the first pane in the agents window to use as split target
|
|
154
|
+
const listResult = await runTmuxCommand([
|
|
155
|
+
'list-panes',
|
|
156
|
+
'-t',
|
|
157
|
+
agentsWindowId,
|
|
158
|
+
'-F',
|
|
159
|
+
'#{pane_id}',
|
|
160
|
+
]);
|
|
161
|
+
if (!listResult.success || !listResult.output) {
|
|
162
|
+
// Fallback: create new window (with retry counter)
|
|
163
|
+
agentsWindowId = undefined;
|
|
164
|
+
return spawnInAgentsWindow(action, ctx, retryCount + 1);
|
|
165
|
+
}
|
|
166
|
+
const targetPaneId = listResult.output.split('\n')[0]?.trim();
|
|
167
|
+
if (!targetPaneId) {
|
|
168
|
+
// Fallback: create new window (with retry counter)
|
|
169
|
+
agentsWindowId = undefined;
|
|
170
|
+
return spawnInAgentsWindow(action, ctx, retryCount + 1);
|
|
171
|
+
}
|
|
172
|
+
// Split within the agents window
|
|
173
|
+
const splitResult = await runTmuxCommand([
|
|
174
|
+
'split-window',
|
|
175
|
+
action.splitDirection,
|
|
176
|
+
'-t',
|
|
177
|
+
targetPaneId,
|
|
178
|
+
'-P',
|
|
179
|
+
'-F',
|
|
180
|
+
'#{pane_id}',
|
|
181
|
+
command,
|
|
182
|
+
]);
|
|
183
|
+
if (!splitResult.success) {
|
|
184
|
+
return { success: false, error: splitResult.output };
|
|
185
|
+
}
|
|
186
|
+
const paneId = splitResult.output?.trim();
|
|
187
|
+
// Apply the configured layout to the agents window (e.g., tiled for grid)
|
|
188
|
+
if (agentsWindowId && layout) {
|
|
189
|
+
await runTmuxCommand(['select-layout', '-t', agentsWindowId, layout]);
|
|
190
|
+
}
|
|
191
|
+
return {
|
|
192
|
+
success: true,
|
|
193
|
+
paneId: paneId || undefined,
|
|
194
|
+
windowId: agentsWindowId,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Reset the agents window state (for cleanup)
|
|
199
|
+
*/
|
|
200
|
+
export function resetAgentsWindow() {
|
|
201
|
+
agentsWindowId = undefined;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Close the agents window if it exists
|
|
205
|
+
* This kills the entire window, which closes all panes within it
|
|
206
|
+
*/
|
|
207
|
+
export async function closeAgentsWindow() {
|
|
208
|
+
if (!agentsWindowId)
|
|
209
|
+
return;
|
|
210
|
+
// Kill the entire window (closes all panes within it)
|
|
211
|
+
await runTmuxCommand(['kill-window', '-t', agentsWindowId]);
|
|
212
|
+
agentsWindowId = undefined;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Synchronously close the agents window (for shutdown)
|
|
216
|
+
* Uses spawnSync to ensure it completes before process exit
|
|
217
|
+
*/
|
|
218
|
+
export function closeAgentsWindowSync() {
|
|
219
|
+
if (!agentsWindowId)
|
|
220
|
+
return;
|
|
221
|
+
// Kill the entire window synchronously
|
|
222
|
+
runTmuxCommandSync(['kill-window', '-t', agentsWindowId]);
|
|
223
|
+
agentsWindowId = undefined;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Get the current agents window ID (for testing/debugging)
|
|
227
|
+
*/
|
|
228
|
+
export function getAgentsWindowId() {
|
|
229
|
+
return agentsWindowId;
|
|
230
|
+
}
|
|
231
|
+
//# sourceMappingURL=executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../../src/tmux/executor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from './types';
|
|
2
|
+
export * from './utils';
|
|
3
|
+
export { queryWindowState } from './state-query';
|
|
4
|
+
export { decideSpawnActions, calculateCapacity } from './decision-engine';
|
|
5
|
+
export { executeAction, executeActions, closeAgentsWindow, closeAgentsWindowSync, } from './executor';
|
|
6
|
+
export { TmuxSessionManager } from './manager';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tmux/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC1E,OAAO,EACN,aAAa,EACb,cAAc,EACd,iBAAiB,EACjB,qBAAqB,GACrB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from './types';
|
|
2
|
+
export * from './utils';
|
|
3
|
+
export { queryWindowState } from './state-query';
|
|
4
|
+
export { decideSpawnActions, calculateCapacity } from './decision-engine';
|
|
5
|
+
export { executeAction, executeActions, closeAgentsWindow, closeAgentsWindowSync, } from './executor';
|
|
6
|
+
export { TmuxSessionManager } from './manager';
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tmux/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC1E,OAAO,EACN,aAAa,EACb,cAAc,EACd,iBAAiB,EACjB,qBAAqB,GACrB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { PluginInput } from '@opencode-ai/plugin';
|
|
2
|
+
import type { TmuxConfig } from './types';
|
|
3
|
+
export interface TmuxSessionManagerCallbacks {
|
|
4
|
+
onLog?: (message: string) => void;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Manages tmux panes for background agents.
|
|
8
|
+
*
|
|
9
|
+
* Architecture:
|
|
10
|
+
* 1. QUERY: Get actual tmux pane state (source of truth)
|
|
11
|
+
* 2. DECIDE: Pure function determines actions based on state
|
|
12
|
+
* 3. EXECUTE: Execute actions with verification
|
|
13
|
+
* 4. UPDATE: Update internal cache only after tmux confirms success
|
|
14
|
+
*/
|
|
15
|
+
export declare class TmuxSessionManager {
|
|
16
|
+
private ctx;
|
|
17
|
+
private config;
|
|
18
|
+
private callbacks?;
|
|
19
|
+
private sessions;
|
|
20
|
+
private pendingSessions;
|
|
21
|
+
private pollInterval?;
|
|
22
|
+
private sourcePaneId;
|
|
23
|
+
constructor(ctx: PluginInput, config: TmuxConfig, callbacks?: TmuxSessionManagerCallbacks | undefined);
|
|
24
|
+
/**
|
|
25
|
+
* Check if tmux integration is enabled and available
|
|
26
|
+
*/
|
|
27
|
+
isEnabled(): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Handle a new background session being created
|
|
30
|
+
* This is called by BackgroundManager when a background task starts
|
|
31
|
+
*/
|
|
32
|
+
onSessionCreated(event: {
|
|
33
|
+
sessionId: string;
|
|
34
|
+
parentId: string;
|
|
35
|
+
title: string;
|
|
36
|
+
}): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Handle a session being deleted
|
|
39
|
+
*
|
|
40
|
+
* Explicitly kills the pane when a background session completes.
|
|
41
|
+
* We can't rely on `opencode attach` exiting because it's an interactive
|
|
42
|
+
* terminal that keeps running even after the session goes idle.
|
|
43
|
+
*/
|
|
44
|
+
onSessionDeleted(event: {
|
|
45
|
+
sessionId: string;
|
|
46
|
+
}): Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* Clean up all panes on shutdown
|
|
49
|
+
*
|
|
50
|
+
* Kills the entire "Agents" window, which closes all agent panes at once.
|
|
51
|
+
*/
|
|
52
|
+
cleanup(): Promise<void>;
|
|
53
|
+
/**
|
|
54
|
+
* Synchronous cleanup for shutdown (ensures completion before exit)
|
|
55
|
+
*
|
|
56
|
+
* Uses spawnSync to guarantee the tmux commands complete before the
|
|
57
|
+
* process exits, which is necessary for signal handlers.
|
|
58
|
+
*/
|
|
59
|
+
cleanupSync(): void;
|
|
60
|
+
/**
|
|
61
|
+
* Start polling for session status
|
|
62
|
+
*/
|
|
63
|
+
private startPolling;
|
|
64
|
+
/**
|
|
65
|
+
* Stop polling
|
|
66
|
+
*/
|
|
67
|
+
private stopPolling;
|
|
68
|
+
/**
|
|
69
|
+
* Poll active sessions for status changes
|
|
70
|
+
*/
|
|
71
|
+
private pollSessions;
|
|
72
|
+
/**
|
|
73
|
+
* Get session mappings for decision engine
|
|
74
|
+
*/
|
|
75
|
+
private getSessionMappings;
|
|
76
|
+
private getServerUrl;
|
|
77
|
+
private applyActionResults;
|
|
78
|
+
private log;
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/tmux/manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAEX,UAAU,EAKV,MAAM,SAAS,CAAC;AA2BjB,MAAM,WAAW,2BAA2B;IAC3C,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAED;;;;;;;;GAQG;AACH,qBAAa,kBAAkB;IAO7B,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,SAAS,CAAC;IARnB,OAAO,CAAC,QAAQ,CAAqC;IACrD,OAAO,CAAC,eAAe,CAAqB;IAC5C,OAAO,CAAC,YAAY,CAAC,CAAiC;IACtD,OAAO,CAAC,YAAY,CAAqB;gBAGhC,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,UAAU,EAClB,SAAS,CAAC,EAAE,2BAA2B,YAAA;IAKhD;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;;OAGG;IACG,gBAAgB,CAAC,KAAK,EAAE;QAC7B,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;KACd,GAAG,OAAO,CAAC,IAAI,CAAC;IAiFjB;;;;;;OAMG;IACG,gBAAgB,CAAC,KAAK,EAAE;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBnE;;;;OAIG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ9B;;;;;OAKG;IACH,WAAW,IAAI,IAAI;IAQnB;;OAEG;IACH,OAAO,CAAC,YAAY;IAOpB;;OAEG;IACH,OAAO,CAAC,WAAW;IAMnB;;OAEG;YACW,YAAY;IAgC1B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAQ1B,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,kBAAkB;IAiC1B,OAAO,CAAC,GAAG;CAGX"}
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import { POLL_INTERVAL_MS, SESSION_MISSING_GRACE_MS, SESSION_TIMEOUT_MS } from './types';
|
|
2
|
+
import { getCurrentPaneId, getTmuxPath, isInsideTmux } from './utils';
|
|
3
|
+
import { queryWindowState } from './state-query';
|
|
4
|
+
import { decideSpawnActions } from './decision-engine';
|
|
5
|
+
import { executeActions, closeAgentsWindow, closeAgentsWindowSync, closePaneById, } from './executor';
|
|
6
|
+
/**
|
|
7
|
+
* Check if the OpenCode server is running by hitting the health endpoint
|
|
8
|
+
*/
|
|
9
|
+
async function isServerRunning(serverUrl) {
|
|
10
|
+
try {
|
|
11
|
+
const healthUrl = new URL('/health', serverUrl).toString();
|
|
12
|
+
const response = await fetch(healthUrl, {
|
|
13
|
+
signal: AbortSignal.timeout(2000),
|
|
14
|
+
});
|
|
15
|
+
return response.ok;
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Manages tmux panes for background agents.
|
|
23
|
+
*
|
|
24
|
+
* Architecture:
|
|
25
|
+
* 1. QUERY: Get actual tmux pane state (source of truth)
|
|
26
|
+
* 2. DECIDE: Pure function determines actions based on state
|
|
27
|
+
* 3. EXECUTE: Execute actions with verification
|
|
28
|
+
* 4. UPDATE: Update internal cache only after tmux confirms success
|
|
29
|
+
*/
|
|
30
|
+
export class TmuxSessionManager {
|
|
31
|
+
ctx;
|
|
32
|
+
config;
|
|
33
|
+
callbacks;
|
|
34
|
+
sessions = new Map();
|
|
35
|
+
pendingSessions = new Set();
|
|
36
|
+
pollInterval;
|
|
37
|
+
sourcePaneId;
|
|
38
|
+
constructor(ctx, config, callbacks) {
|
|
39
|
+
this.ctx = ctx;
|
|
40
|
+
this.config = config;
|
|
41
|
+
this.callbacks = callbacks;
|
|
42
|
+
this.sourcePaneId = getCurrentPaneId();
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Check if tmux integration is enabled and available
|
|
46
|
+
*/
|
|
47
|
+
isEnabled() {
|
|
48
|
+
return this.config.enabled && isInsideTmux();
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Handle a new background session being created
|
|
52
|
+
* This is called by BackgroundManager when a background task starts
|
|
53
|
+
*/
|
|
54
|
+
async onSessionCreated(event) {
|
|
55
|
+
if (!this.isEnabled())
|
|
56
|
+
return;
|
|
57
|
+
if (this.pendingSessions.has(event.sessionId) || this.sessions.has(event.sessionId))
|
|
58
|
+
return;
|
|
59
|
+
this.pendingSessions.add(event.sessionId);
|
|
60
|
+
try {
|
|
61
|
+
const tmuxPath = await getTmuxPath();
|
|
62
|
+
if (!tmuxPath) {
|
|
63
|
+
this.log('tmux binary not found.');
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (!this.sourcePaneId) {
|
|
67
|
+
this.sourcePaneId = getCurrentPaneId();
|
|
68
|
+
}
|
|
69
|
+
if (!this.sourcePaneId) {
|
|
70
|
+
this.log('Unable to determine source pane id.');
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const state = await queryWindowState(this.sourcePaneId);
|
|
74
|
+
if (!state) {
|
|
75
|
+
this.log('Failed to query tmux window state.');
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const decision = decideSpawnActions(state, event.sessionId, event.title, {
|
|
79
|
+
mainPaneMinWidth: this.config.mainPaneMinWidth,
|
|
80
|
+
agentPaneMinWidth: this.config.agentPaneMinWidth,
|
|
81
|
+
maxPanes: this.config.maxPanes,
|
|
82
|
+
}, this.getSessionMappings());
|
|
83
|
+
if (!decision.canSpawn) {
|
|
84
|
+
if (decision.reason) {
|
|
85
|
+
this.log(`Cannot spawn pane: ${decision.reason}`);
|
|
86
|
+
}
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const serverUrl = this.getServerUrl();
|
|
90
|
+
if (!serverUrl) {
|
|
91
|
+
this.log('Unable to determine OpenCode server URL.');
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
// Check if server is actually running before attempting to spawn
|
|
95
|
+
const serverRunning = await isServerRunning(serverUrl);
|
|
96
|
+
if (!serverRunning) {
|
|
97
|
+
this.log(`Server not running at ${serverUrl}. Start opencode with --port flag to enable tmux integration.`);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
const result = await executeActions(decision.actions, {
|
|
101
|
+
config: this.config,
|
|
102
|
+
serverUrl,
|
|
103
|
+
windowState: state,
|
|
104
|
+
});
|
|
105
|
+
if (!result.success) {
|
|
106
|
+
this.log('Failed to execute tmux actions.');
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
this.applyActionResults(decision.actions, result.spawnedPaneId);
|
|
110
|
+
if (this.sessions.size > 0) {
|
|
111
|
+
this.startPolling();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
finally {
|
|
115
|
+
this.pendingSessions.delete(event.sessionId);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Handle a session being deleted
|
|
120
|
+
*
|
|
121
|
+
* Explicitly kills the pane when a background session completes.
|
|
122
|
+
* We can't rely on `opencode attach` exiting because it's an interactive
|
|
123
|
+
* terminal that keeps running even after the session goes idle.
|
|
124
|
+
*/
|
|
125
|
+
async onSessionDeleted(event) {
|
|
126
|
+
if (!this.isEnabled())
|
|
127
|
+
return;
|
|
128
|
+
// Find the session in our mappings
|
|
129
|
+
const session = this.sessions.get(event.sessionId);
|
|
130
|
+
if (!session)
|
|
131
|
+
return;
|
|
132
|
+
// Kill the pane explicitly - opencode attach won't exit on its own
|
|
133
|
+
const result = await closePaneById(session.paneId);
|
|
134
|
+
if (!result.success) {
|
|
135
|
+
this.log(`Failed to close pane ${session.paneId}: ${result.error}`);
|
|
136
|
+
}
|
|
137
|
+
// Update internal state
|
|
138
|
+
this.sessions.delete(event.sessionId);
|
|
139
|
+
if (this.sessions.size === 0) {
|
|
140
|
+
this.stopPolling();
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Clean up all panes on shutdown
|
|
145
|
+
*
|
|
146
|
+
* Kills the entire "Agents" window, which closes all agent panes at once.
|
|
147
|
+
*/
|
|
148
|
+
async cleanup() {
|
|
149
|
+
this.stopPolling();
|
|
150
|
+
// Kill the entire agents window - this closes all panes at once
|
|
151
|
+
await closeAgentsWindow();
|
|
152
|
+
this.sessions.clear();
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Synchronous cleanup for shutdown (ensures completion before exit)
|
|
156
|
+
*
|
|
157
|
+
* Uses spawnSync to guarantee the tmux commands complete before the
|
|
158
|
+
* process exits, which is necessary for signal handlers.
|
|
159
|
+
*/
|
|
160
|
+
cleanupSync() {
|
|
161
|
+
this.stopPolling();
|
|
162
|
+
// Kill the entire agents window synchronously
|
|
163
|
+
closeAgentsWindowSync();
|
|
164
|
+
this.sessions.clear();
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Start polling for session status
|
|
168
|
+
*/
|
|
169
|
+
startPolling() {
|
|
170
|
+
if (this.pollInterval)
|
|
171
|
+
return;
|
|
172
|
+
this.pollInterval = setInterval(() => {
|
|
173
|
+
void this.pollSessions();
|
|
174
|
+
}, POLL_INTERVAL_MS);
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Stop polling
|
|
178
|
+
*/
|
|
179
|
+
stopPolling() {
|
|
180
|
+
if (!this.pollInterval)
|
|
181
|
+
return;
|
|
182
|
+
clearInterval(this.pollInterval);
|
|
183
|
+
this.pollInterval = undefined;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Poll active sessions for status changes
|
|
187
|
+
*/
|
|
188
|
+
async pollSessions() {
|
|
189
|
+
if (!this.isEnabled())
|
|
190
|
+
return;
|
|
191
|
+
if (!this.sourcePaneId)
|
|
192
|
+
return;
|
|
193
|
+
const state = await queryWindowState(this.sourcePaneId);
|
|
194
|
+
if (!state)
|
|
195
|
+
return;
|
|
196
|
+
const now = Date.now();
|
|
197
|
+
for (const session of this.sessions.values()) {
|
|
198
|
+
const pane = findPane(state, session.paneId);
|
|
199
|
+
if (pane) {
|
|
200
|
+
session.lastSeenAt = new Date();
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
const missingFor = now - session.lastSeenAt.getTime();
|
|
204
|
+
if (missingFor > SESSION_MISSING_GRACE_MS) {
|
|
205
|
+
this.sessions.delete(session.sessionId);
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
const age = now - session.createdAt.getTime();
|
|
209
|
+
if (age > SESSION_TIMEOUT_MS) {
|
|
210
|
+
this.sessions.delete(session.sessionId);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
if (this.sessions.size === 0) {
|
|
214
|
+
this.stopPolling();
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Get session mappings for decision engine
|
|
219
|
+
*/
|
|
220
|
+
getSessionMappings() {
|
|
221
|
+
return Array.from(this.sessions.values()).map((session) => ({
|
|
222
|
+
sessionId: session.sessionId,
|
|
223
|
+
paneId: session.paneId,
|
|
224
|
+
createdAt: session.createdAt,
|
|
225
|
+
}));
|
|
226
|
+
}
|
|
227
|
+
getServerUrl() {
|
|
228
|
+
const ctx = this.ctx;
|
|
229
|
+
const serverUrl = ctx.serverUrl ?? ctx.baseUrl ?? ctx.client?.baseUrl;
|
|
230
|
+
if (!serverUrl)
|
|
231
|
+
return undefined;
|
|
232
|
+
return typeof serverUrl === 'string' ? serverUrl : serverUrl.toString();
|
|
233
|
+
}
|
|
234
|
+
applyActionResults(actions, spawnedPaneId) {
|
|
235
|
+
const now = new Date();
|
|
236
|
+
for (const action of actions) {
|
|
237
|
+
switch (action.type) {
|
|
238
|
+
case 'close':
|
|
239
|
+
this.sessions.delete(action.sessionId);
|
|
240
|
+
break;
|
|
241
|
+
case 'replace':
|
|
242
|
+
this.sessions.delete(action.oldSessionId);
|
|
243
|
+
this.sessions.set(action.newSessionId, {
|
|
244
|
+
sessionId: action.newSessionId,
|
|
245
|
+
paneId: action.paneId,
|
|
246
|
+
description: action.description,
|
|
247
|
+
createdAt: now,
|
|
248
|
+
lastSeenAt: now,
|
|
249
|
+
});
|
|
250
|
+
break;
|
|
251
|
+
case 'spawn': {
|
|
252
|
+
const paneId = spawnedPaneId;
|
|
253
|
+
if (!paneId)
|
|
254
|
+
break;
|
|
255
|
+
this.sessions.set(action.sessionId, {
|
|
256
|
+
sessionId: action.sessionId,
|
|
257
|
+
paneId,
|
|
258
|
+
description: action.description,
|
|
259
|
+
createdAt: now,
|
|
260
|
+
lastSeenAt: now,
|
|
261
|
+
});
|
|
262
|
+
break;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
log(message) {
|
|
268
|
+
this.callbacks?.onLog?.(`[tmux] ${message}`);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
function findPane(state, paneId) {
|
|
272
|
+
if (state.mainPane?.paneId === paneId)
|
|
273
|
+
return state.mainPane;
|
|
274
|
+
return state.agentPanes.find((pane) => pane.paneId === paneId);
|
|
275
|
+
}
|
|
276
|
+
//# sourceMappingURL=manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/tmux/manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { WindowState } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Query the current tmux window state
|
|
4
|
+
* Returns information about all panes in the current window
|
|
5
|
+
*/
|
|
6
|
+
export declare function queryWindowState(sourcePaneId: string): Promise<WindowState | null>;
|
|
7
|
+
//# sourceMappingURL=state-query.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-query.d.ts","sourceRoot":"","sources":["../../src/tmux/state-query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAgB,MAAM,SAAS,CAAC;AAGzD;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAkExF"}
|