maestro-flow 0.1.1 → 0.1.3
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/.codex/skills/manage-codebase-rebuild/SKILL.md +405 -405
- package/.codex/skills/manage-codebase-refresh/SKILL.md +82 -82
- package/.codex/skills/manage-issue/SKILL.md +65 -65
- package/.codex/skills/manage-status/SKILL.md +89 -89
- package/.codex/skills/quality-debug/SKILL.md +413 -413
- package/.codex/skills/quality-refactor/SKILL.md +191 -191
- package/.codex/skills/quality-sync/SKILL.md +89 -89
- package/.codex/skills/quality-test/SKILL.md +198 -198
- package/.codex/skills/spec-add/SKILL.md +79 -79
- package/.codex/skills/spec-load/SKILL.md +75 -75
- package/.codex/skills/spec-map/SKILL.md +182 -182
- package/.codex/skills/spec-setup/SKILL.md +76 -76
- package/.codex/skills/team-coordinate/SKILL.md +7 -7
- package/.codex/skills/team-coordinate/roles/coordinator/role.md +1 -1
- package/.codex/skills/team-lifecycle-v4/SKILL.md +2 -2
- package/.codex/skills/team-lifecycle-v4/instructions/agent-instruction.md +2 -2
- package/.codex/skills/team-lifecycle-v4/roles/analyst/role.md +2 -2
- package/.codex/skills/team-lifecycle-v4/roles/coordinator/role.md +2 -2
- package/.codex/skills/team-lifecycle-v4/roles/executor/commands/implement.md +1 -1
- package/.codex/skills/team-lifecycle-v4/roles/planner/role.md +2 -2
- package/.codex/skills/team-lifecycle-v4/roles/writer/role.md +1 -1
- package/.codex/skills/team-lifecycle-v4/schemas/tasks-schema.md +1 -1
- package/.codex/skills/team-quality-assurance/SKILL.md +2 -2
- package/.codex/skills/team-quality-assurance/roles/coordinator/role.md +2 -2
- package/.codex/skills/team-quality-assurance/roles/executor/role.md +1 -1
- package/.codex/skills/team-quality-assurance/roles/scout/role.md +2 -2
- package/.codex/skills/team-review/SKILL.md +2 -2
- package/.codex/skills/team-review/roles/coordinator/role.md +2 -2
- package/.codex/skills/team-review/roles/reviewer/role.md +2 -2
- package/.codex/skills/team-review/roles/scanner/role.md +1 -1
- package/.codex/skills/team-tech-debt/SKILL.md +2 -2
- package/.codex/skills/team-tech-debt/roles/coordinator/role.md +1 -1
- package/.codex/skills/team-tech-debt/roles/executor/role.md +1 -1
- package/.codex/skills/team-tech-debt/roles/scanner/role.md +2 -2
- package/.codex/skills/team-tech-debt/roles/validator/role.md +1 -1
- package/.codex/skills/team-testing/SKILL.md +2 -2
- package/.codex/skills/team-testing/roles/coordinator/role.md +2 -2
- package/.codex/skills/team-testing/roles/executor/role.md +2 -2
- package/.codex/skills/team-testing/roles/generator/role.md +2 -2
- package/README.md +43 -4
- package/dist/agents/dashboard-bridge.d.ts +5 -0
- package/dist/agents/dashboard-bridge.d.ts.map +1 -1
- package/dist/agents/dashboard-bridge.js +13 -0
- package/dist/agents/dashboard-bridge.js.map +1 -1
- package/dist/agents/parallel-cli-runner.d.ts +42 -0
- package/dist/agents/parallel-cli-runner.d.ts.map +1 -0
- package/dist/agents/parallel-cli-runner.js +200 -0
- package/dist/agents/parallel-cli-runner.js.map +1 -0
- package/dist/agents/terminal-adapter.d.ts +94 -0
- package/dist/agents/terminal-adapter.d.ts.map +1 -0
- package/dist/agents/terminal-adapter.js +132 -0
- package/dist/agents/terminal-adapter.js.map +1 -0
- package/dist/agents/terminal-backend.d.ts +53 -0
- package/dist/agents/terminal-backend.d.ts.map +1 -0
- package/dist/agents/terminal-backend.js +286 -0
- package/dist/agents/terminal-backend.js.map +1 -0
- package/dist/cli.js +4 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/coordinate.d.ts.map +1 -1
- package/dist/commands/coordinate.js +14 -5
- package/dist/commands/coordinate.js.map +1 -1
- package/dist/commands/delegate.d.ts +3 -0
- package/dist/commands/delegate.d.ts.map +1 -0
- package/dist/commands/delegate.js +142 -0
- package/dist/commands/delegate.js.map +1 -0
- package/dist/commands/msg.d.ts +3 -0
- package/dist/commands/msg.d.ts.map +1 -0
- package/dist/commands/msg.js +110 -0
- package/dist/commands/msg.js.map +1 -0
- package/dist/coordinator/graph-types.d.ts +17 -0
- package/dist/coordinator/graph-types.d.ts.map +1 -1
- package/dist/coordinator/graph-walker.d.ts +3 -1
- package/dist/coordinator/graph-walker.d.ts.map +1 -1
- package/dist/coordinator/graph-walker.js +147 -8
- package/dist/coordinator/graph-walker.js.map +1 -1
- package/dist/coordinator/index.d.ts +2 -0
- package/dist/coordinator/index.d.ts.map +1 -1
- package/dist/coordinator/index.js +1 -0
- package/dist/coordinator/index.js.map +1 -1
- package/dist/coordinator/parallel-executor.d.ts +24 -0
- package/dist/coordinator/parallel-executor.d.ts.map +1 -0
- package/dist/coordinator/parallel-executor.js +43 -0
- package/dist/coordinator/parallel-executor.js.map +1 -0
- package/package.json +4 -2
- package/templates/cli/prompts/rules-tech-rules-agent-prompt.txt +89 -89
- package/templates/cli/prompts/workflow-codex-feasibility-validation.txt +176 -176
- package/templates/cli/prompts/workflow-gemini-solution-design.txt +131 -131
- package/templates/cli/prompts/workflow-skill-index.txt +224 -224
- package/templates/cli/protocols/analysis-protocol.md +2 -2
- package/templates/cli/protocols/write-protocol.md +2 -2
- package/workflows/memory.md +2 -2
- package/.codex/skills/team-lifecycle-v4/MIGRATION-PLAN.md +0 -512
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { SpawnFn } from '../coordinator/cli-executor.js';
|
|
2
|
+
export interface ParallelTask {
|
|
3
|
+
id: string;
|
|
4
|
+
prompt: string;
|
|
5
|
+
tool: string;
|
|
6
|
+
workDir: string;
|
|
7
|
+
mode: 'analysis' | 'write';
|
|
8
|
+
backend?: 'direct' | 'terminal';
|
|
9
|
+
sessionKey?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface ParallelResult {
|
|
12
|
+
id: string;
|
|
13
|
+
success: boolean;
|
|
14
|
+
output: string;
|
|
15
|
+
execId: string;
|
|
16
|
+
durationMs: number;
|
|
17
|
+
}
|
|
18
|
+
export interface RunAllOptions {
|
|
19
|
+
maxConcurrency?: number;
|
|
20
|
+
joinStrategy: 'all' | 'any' | 'majority';
|
|
21
|
+
signal?: AbortSignal;
|
|
22
|
+
}
|
|
23
|
+
export declare class ParallelCliRunner {
|
|
24
|
+
private readonly spawn;
|
|
25
|
+
constructor(spawn: SpawnFn);
|
|
26
|
+
/**
|
|
27
|
+
* Execute tasks in parallel with session-key grouping and join strategy.
|
|
28
|
+
*
|
|
29
|
+
* Tasks sharing the same sessionKey (defaults to tool+workDir) execute
|
|
30
|
+
* serially within their group. Different groups run in parallel, limited
|
|
31
|
+
* by maxConcurrency.
|
|
32
|
+
*/
|
|
33
|
+
runAll(tasks: ParallelTask[], options: RunAllOptions): Promise<{
|
|
34
|
+
results: ParallelResult[];
|
|
35
|
+
success: boolean;
|
|
36
|
+
}>;
|
|
37
|
+
private groupBySession;
|
|
38
|
+
private runSessionGroup;
|
|
39
|
+
private executeTask;
|
|
40
|
+
private evaluateJoin;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=parallel-cli-runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parallel-cli-runner.d.ts","sourceRoot":"","sources":["../../src/agents/parallel-cli-runner.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAmB9D,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC;IAC3B,OAAO,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,KAAK,GAAG,KAAK,GAAG,UAAU,CAAC;IACzC,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AA0CD,qBAAa,iBAAiB;IAChB,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,EAAE,OAAO;IAE3C;;;;;;OAMG;IACG,MAAM,CACV,KAAK,EAAE,YAAY,EAAE,EACrB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC;QAAE,OAAO,EAAE,cAAc,EAAE,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAsD3D,OAAO,CAAC,cAAc;YAcR,eAAe;YA4Bf,WAAW;IA0DzB,OAAO,CAAC,YAAY;CAgBrB"}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Parallel CLI Runner — Async multi-CLI scheduler with semaphore concurrency.
|
|
3
|
+
// Standalone scheduler with SpawnFn injection, decoupled from GraphWalker.
|
|
4
|
+
//
|
|
5
|
+
// Concurrency model (from Bridge's PerSessionWorkerPool):
|
|
6
|
+
// - Tasks with same sessionKey (tool+workDir) run serially
|
|
7
|
+
// - Tasks with different sessionKeys run in parallel
|
|
8
|
+
// - Global maxConcurrency limits total parallel processes
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
// Tool name -> AgentType mapping (mirrors cli-agent-runner.ts)
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
const TOOL_TO_AGENT_TYPE = {
|
|
14
|
+
gemini: 'gemini',
|
|
15
|
+
qwen: 'qwen',
|
|
16
|
+
codex: 'codex',
|
|
17
|
+
claude: 'claude-code',
|
|
18
|
+
opencode: 'opencode',
|
|
19
|
+
};
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
// Semaphore — simple counter-based concurrency limiter
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
class Semaphore {
|
|
24
|
+
max;
|
|
25
|
+
current = 0;
|
|
26
|
+
waiters = [];
|
|
27
|
+
constructor(max) {
|
|
28
|
+
this.max = max;
|
|
29
|
+
}
|
|
30
|
+
async acquire() {
|
|
31
|
+
if (this.current < this.max) {
|
|
32
|
+
this.current++;
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
return new Promise((resolve) => {
|
|
36
|
+
this.waiters.push(() => {
|
|
37
|
+
this.current++;
|
|
38
|
+
resolve();
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
release() {
|
|
43
|
+
this.current--;
|
|
44
|
+
const next = this.waiters.shift();
|
|
45
|
+
if (next)
|
|
46
|
+
next();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
// Default per-task timeout (10 min ceiling)
|
|
51
|
+
// ---------------------------------------------------------------------------
|
|
52
|
+
const DEFAULT_TASK_TIMEOUT_MS = 10 * 60 * 1000;
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
// ParallelCliRunner
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
export class ParallelCliRunner {
|
|
57
|
+
spawn;
|
|
58
|
+
constructor(spawn) {
|
|
59
|
+
this.spawn = spawn;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Execute tasks in parallel with session-key grouping and join strategy.
|
|
63
|
+
*
|
|
64
|
+
* Tasks sharing the same sessionKey (defaults to tool+workDir) execute
|
|
65
|
+
* serially within their group. Different groups run in parallel, limited
|
|
66
|
+
* by maxConcurrency.
|
|
67
|
+
*/
|
|
68
|
+
async runAll(tasks, options) {
|
|
69
|
+
const { maxConcurrency = 4, joinStrategy, signal: globalSignal, } = options;
|
|
70
|
+
if (tasks.length === 0) {
|
|
71
|
+
return { results: [], success: true };
|
|
72
|
+
}
|
|
73
|
+
// Group by session key
|
|
74
|
+
const groups = this.groupBySession(tasks);
|
|
75
|
+
const semaphore = new Semaphore(maxConcurrency);
|
|
76
|
+
const results = [];
|
|
77
|
+
// For 'any' strategy, wrap global signal so we can abort remaining
|
|
78
|
+
// groups once the first group completes.
|
|
79
|
+
const effectiveAbort = joinStrategy === 'any'
|
|
80
|
+
? new AbortController()
|
|
81
|
+
: undefined;
|
|
82
|
+
if (effectiveAbort && globalSignal) {
|
|
83
|
+
globalSignal.addEventListener('abort', () => effectiveAbort.abort(), { once: true });
|
|
84
|
+
}
|
|
85
|
+
const effectiveSignal = effectiveAbort?.signal ?? globalSignal;
|
|
86
|
+
// Create per-group serial chains, run groups in parallel
|
|
87
|
+
const groupPromises = [...groups.values()].map((queue) => this.runSessionGroup(queue, semaphore, results, effectiveSignal));
|
|
88
|
+
if (joinStrategy === 'any') {
|
|
89
|
+
// First group to finish triggers abort of the rest
|
|
90
|
+
await Promise.race(groupPromises);
|
|
91
|
+
effectiveAbort.abort();
|
|
92
|
+
await Promise.allSettled(groupPromises);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
// 'all' and 'majority' both wait for all groups to settle
|
|
96
|
+
await Promise.allSettled(groupPromises);
|
|
97
|
+
}
|
|
98
|
+
const success = this.evaluateJoin(results, tasks.length, joinStrategy);
|
|
99
|
+
return { results, success };
|
|
100
|
+
}
|
|
101
|
+
// -------------------------------------------------------------------------
|
|
102
|
+
// Session grouping
|
|
103
|
+
// -------------------------------------------------------------------------
|
|
104
|
+
groupBySession(tasks) {
|
|
105
|
+
const groups = new Map();
|
|
106
|
+
for (const task of tasks) {
|
|
107
|
+
const key = task.sessionKey ?? `${task.tool}:${task.workDir}`;
|
|
108
|
+
if (!groups.has(key))
|
|
109
|
+
groups.set(key, []);
|
|
110
|
+
groups.get(key).push(task);
|
|
111
|
+
}
|
|
112
|
+
return groups;
|
|
113
|
+
}
|
|
114
|
+
// -------------------------------------------------------------------------
|
|
115
|
+
// Serial execution within a session group
|
|
116
|
+
// -------------------------------------------------------------------------
|
|
117
|
+
async runSessionGroup(queue, semaphore, results, signal) {
|
|
118
|
+
for (const task of queue) {
|
|
119
|
+
if (signal?.aborted)
|
|
120
|
+
break;
|
|
121
|
+
await semaphore.acquire();
|
|
122
|
+
if (signal?.aborted) {
|
|
123
|
+
semaphore.release();
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
try {
|
|
127
|
+
const result = await this.executeTask(task, signal);
|
|
128
|
+
results.push(result);
|
|
129
|
+
}
|
|
130
|
+
finally {
|
|
131
|
+
semaphore.release();
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
// -------------------------------------------------------------------------
|
|
136
|
+
// Single task execution via SpawnFn
|
|
137
|
+
// -------------------------------------------------------------------------
|
|
138
|
+
async executeTask(task, globalSignal) {
|
|
139
|
+
const startTime = Date.now();
|
|
140
|
+
const agentType = TOOL_TO_AGENT_TYPE[task.tool];
|
|
141
|
+
if (!agentType) {
|
|
142
|
+
return {
|
|
143
|
+
id: task.id,
|
|
144
|
+
success: false,
|
|
145
|
+
output: `Unknown tool: ${task.tool}`,
|
|
146
|
+
execId: '',
|
|
147
|
+
durationMs: Date.now() - startTime,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
// Per-task abort: merges global signal + timeout ceiling
|
|
151
|
+
const taskAbort = new AbortController();
|
|
152
|
+
const timeout = setTimeout(() => taskAbort.abort(), DEFAULT_TASK_TIMEOUT_MS);
|
|
153
|
+
const onGlobalAbort = () => taskAbort.abort();
|
|
154
|
+
globalSignal?.addEventListener('abort', onGlobalAbort, { once: true });
|
|
155
|
+
try {
|
|
156
|
+
const result = await this.spawn({
|
|
157
|
+
type: agentType,
|
|
158
|
+
prompt: task.prompt,
|
|
159
|
+
workDir: task.workDir,
|
|
160
|
+
approvalMode: task.mode === 'write' ? 'auto' : 'suggest',
|
|
161
|
+
signal: taskAbort.signal,
|
|
162
|
+
});
|
|
163
|
+
return {
|
|
164
|
+
id: task.id,
|
|
165
|
+
success: result.success,
|
|
166
|
+
output: result.output,
|
|
167
|
+
execId: result.execId,
|
|
168
|
+
durationMs: result.durationMs,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
catch (err) {
|
|
172
|
+
return {
|
|
173
|
+
id: task.id,
|
|
174
|
+
success: false,
|
|
175
|
+
output: err instanceof Error ? err.message : String(err),
|
|
176
|
+
execId: '',
|
|
177
|
+
durationMs: Date.now() - startTime,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
finally {
|
|
181
|
+
clearTimeout(timeout);
|
|
182
|
+
globalSignal?.removeEventListener('abort', onGlobalAbort);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// -------------------------------------------------------------------------
|
|
186
|
+
// Join strategy evaluation
|
|
187
|
+
// -------------------------------------------------------------------------
|
|
188
|
+
evaluateJoin(results, totalTasks, strategy) {
|
|
189
|
+
const successCount = results.filter((r) => r.success).length;
|
|
190
|
+
switch (strategy) {
|
|
191
|
+
case 'all':
|
|
192
|
+
return successCount === totalTasks;
|
|
193
|
+
case 'any':
|
|
194
|
+
return successCount >= 1;
|
|
195
|
+
case 'majority':
|
|
196
|
+
return successCount > totalTasks / 2;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
//# sourceMappingURL=parallel-cli-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parallel-cli-runner.js","sourceRoot":"","sources":["../../src/agents/parallel-cli-runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { TerminalBackend } from './terminal-backend.js';
|
|
2
|
+
type AgentType = 'claude-code' | 'codex' | 'gemini' | 'qwen' | 'opencode';
|
|
3
|
+
type AgentProcessStatus = 'spawning' | 'running' | 'paused' | 'stopping' | 'stopped' | 'error';
|
|
4
|
+
interface AgentConfig {
|
|
5
|
+
type: AgentType;
|
|
6
|
+
prompt: string;
|
|
7
|
+
workDir: string;
|
|
8
|
+
env?: Record<string, string>;
|
|
9
|
+
model?: string;
|
|
10
|
+
approvalMode?: 'suggest' | 'auto';
|
|
11
|
+
}
|
|
12
|
+
interface AgentProcess {
|
|
13
|
+
id: string;
|
|
14
|
+
type: AgentType;
|
|
15
|
+
status: AgentProcessStatus;
|
|
16
|
+
config: AgentConfig;
|
|
17
|
+
startedAt: string;
|
|
18
|
+
pid?: number;
|
|
19
|
+
}
|
|
20
|
+
interface NormalizedEntryBase {
|
|
21
|
+
id: string;
|
|
22
|
+
processId: string;
|
|
23
|
+
timestamp: string;
|
|
24
|
+
}
|
|
25
|
+
type NormalizedEntry = (NormalizedEntryBase & {
|
|
26
|
+
type: 'user_message';
|
|
27
|
+
content: string;
|
|
28
|
+
}) | (NormalizedEntryBase & {
|
|
29
|
+
type: 'assistant_message';
|
|
30
|
+
content: string;
|
|
31
|
+
partial: boolean;
|
|
32
|
+
}) | (NormalizedEntryBase & {
|
|
33
|
+
type: 'thinking';
|
|
34
|
+
content: string;
|
|
35
|
+
}) | (NormalizedEntryBase & {
|
|
36
|
+
type: 'tool_use';
|
|
37
|
+
name: string;
|
|
38
|
+
input: Record<string, unknown>;
|
|
39
|
+
status: string;
|
|
40
|
+
result?: string;
|
|
41
|
+
}) | (NormalizedEntryBase & {
|
|
42
|
+
type: 'file_change';
|
|
43
|
+
path: string;
|
|
44
|
+
action: string;
|
|
45
|
+
diff?: string;
|
|
46
|
+
}) | (NormalizedEntryBase & {
|
|
47
|
+
type: 'command_exec';
|
|
48
|
+
command: string;
|
|
49
|
+
exitCode?: number;
|
|
50
|
+
output?: string;
|
|
51
|
+
}) | (NormalizedEntryBase & {
|
|
52
|
+
type: 'approval_request';
|
|
53
|
+
toolName: string;
|
|
54
|
+
toolInput: Record<string, unknown>;
|
|
55
|
+
requestId: string;
|
|
56
|
+
}) | (NormalizedEntryBase & {
|
|
57
|
+
type: 'approval_response';
|
|
58
|
+
requestId: string;
|
|
59
|
+
allowed: boolean;
|
|
60
|
+
}) | (NormalizedEntryBase & {
|
|
61
|
+
type: 'error';
|
|
62
|
+
message: string;
|
|
63
|
+
code?: string;
|
|
64
|
+
}) | (NormalizedEntryBase & {
|
|
65
|
+
type: 'status_change';
|
|
66
|
+
status: AgentProcessStatus;
|
|
67
|
+
reason?: string;
|
|
68
|
+
}) | (NormalizedEntryBase & {
|
|
69
|
+
type: 'token_usage';
|
|
70
|
+
inputTokens: number;
|
|
71
|
+
outputTokens: number;
|
|
72
|
+
cacheReadTokens?: number;
|
|
73
|
+
cacheWriteTokens?: number;
|
|
74
|
+
});
|
|
75
|
+
/** Minimal adapter interface matching BaseAgentAdapter's public surface */
|
|
76
|
+
interface AdapterLike {
|
|
77
|
+
spawn(config: AgentConfig): Promise<AgentProcess>;
|
|
78
|
+
stop(processId: string): Promise<void>;
|
|
79
|
+
onEntry(processId: string, cb: (entry: NormalizedEntry) => void): () => void;
|
|
80
|
+
}
|
|
81
|
+
export declare class TerminalAdapter implements AdapterLike {
|
|
82
|
+
private readonly backend;
|
|
83
|
+
private readonly toolCmd;
|
|
84
|
+
private readonly panes;
|
|
85
|
+
private readonly listeners;
|
|
86
|
+
constructor(backend: TerminalBackend, toolCmd: string);
|
|
87
|
+
spawn(config: AgentConfig): Promise<AgentProcess>;
|
|
88
|
+
stop(processId: string): Promise<void>;
|
|
89
|
+
onEntry(processId: string, cb: (entry: NormalizedEntry) => void): () => void;
|
|
90
|
+
private pollOutput;
|
|
91
|
+
private emit;
|
|
92
|
+
}
|
|
93
|
+
export {};
|
|
94
|
+
//# sourceMappingURL=terminal-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-adapter.d.ts","sourceRoot":"","sources":["../../src/agents/terminal-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Terminal Adapter — wraps TerminalBackend into AdapterLike interface
|
|
3
|
+
// with 2s polling output collection and 120s stale timeout.
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
// Constants
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
const POLL_INTERVAL_MS = 2000;
|
|
9
|
+
const MAX_STALE_CYCLES = 60; // 60 * 2s = 120s stale timeout
|
|
10
|
+
const STARTUP_DELAY_MS = 1000;
|
|
11
|
+
function sleep(ms) {
|
|
12
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
13
|
+
}
|
|
14
|
+
export class TerminalAdapter {
|
|
15
|
+
backend;
|
|
16
|
+
toolCmd;
|
|
17
|
+
panes = new Map();
|
|
18
|
+
listeners = new Map();
|
|
19
|
+
constructor(backend, toolCmd) {
|
|
20
|
+
this.backend = backend;
|
|
21
|
+
this.toolCmd = toolCmd;
|
|
22
|
+
}
|
|
23
|
+
async spawn(config) {
|
|
24
|
+
const processId = `term-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
|
|
25
|
+
// Create pane with the CLI tool running
|
|
26
|
+
const paneId = await this.backend.createPane({
|
|
27
|
+
cwd: config.workDir,
|
|
28
|
+
cmd: this.toolCmd,
|
|
29
|
+
});
|
|
30
|
+
this.panes.set(processId, { paneId, polling: true });
|
|
31
|
+
// Wait for tool to start, then inject prompt
|
|
32
|
+
await sleep(STARTUP_DELAY_MS);
|
|
33
|
+
await this.backend.sendText(paneId, config.prompt);
|
|
34
|
+
// Start polling for output (fire-and-forget async loop)
|
|
35
|
+
this.pollOutput(processId, paneId);
|
|
36
|
+
return {
|
|
37
|
+
id: processId,
|
|
38
|
+
type: config.type,
|
|
39
|
+
status: 'running',
|
|
40
|
+
config,
|
|
41
|
+
startedAt: new Date().toISOString(),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
async stop(processId) {
|
|
45
|
+
const pane = this.panes.get(processId);
|
|
46
|
+
if (!pane)
|
|
47
|
+
return;
|
|
48
|
+
pane.polling = false;
|
|
49
|
+
await this.backend.killPane(pane.paneId);
|
|
50
|
+
this.panes.delete(processId);
|
|
51
|
+
this.emit(processId, {
|
|
52
|
+
id: `${processId}-stop`,
|
|
53
|
+
processId,
|
|
54
|
+
timestamp: new Date().toISOString(),
|
|
55
|
+
type: 'status_change',
|
|
56
|
+
status: 'stopped',
|
|
57
|
+
reason: 'manual stop',
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
onEntry(processId, cb) {
|
|
61
|
+
if (!this.listeners.has(processId)) {
|
|
62
|
+
this.listeners.set(processId, new Set());
|
|
63
|
+
}
|
|
64
|
+
this.listeners.get(processId).add(cb);
|
|
65
|
+
return () => {
|
|
66
|
+
this.listeners.get(processId)?.delete(cb);
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
// -------------------------------------------------------------------------
|
|
70
|
+
// Polling loop — getText diff every 2s, 120s stale timeout
|
|
71
|
+
// -------------------------------------------------------------------------
|
|
72
|
+
async pollOutput(processId, paneId) {
|
|
73
|
+
let lastContent = '';
|
|
74
|
+
let staleCount = 0;
|
|
75
|
+
while (this.panes.get(processId)?.polling) {
|
|
76
|
+
await sleep(POLL_INTERVAL_MS);
|
|
77
|
+
// Check if pane is still alive
|
|
78
|
+
const alive = await this.backend.isAlive(paneId);
|
|
79
|
+
if (!alive) {
|
|
80
|
+
this.emit(processId, {
|
|
81
|
+
id: `${processId}-done`,
|
|
82
|
+
processId,
|
|
83
|
+
timestamp: new Date().toISOString(),
|
|
84
|
+
type: 'status_change',
|
|
85
|
+
status: 'stopped',
|
|
86
|
+
reason: 'pane exited',
|
|
87
|
+
});
|
|
88
|
+
this.panes.delete(processId);
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
// Capture pane content and diff against previous snapshot
|
|
92
|
+
const content = await this.backend.getText(paneId, 100);
|
|
93
|
+
if (content !== lastContent) {
|
|
94
|
+
const newContent = content.slice(lastContent.length);
|
|
95
|
+
if (newContent.trim()) {
|
|
96
|
+
this.emit(processId, {
|
|
97
|
+
id: `${processId}-${Date.now()}`,
|
|
98
|
+
processId,
|
|
99
|
+
timestamp: new Date().toISOString(),
|
|
100
|
+
type: 'assistant_message',
|
|
101
|
+
content: newContent,
|
|
102
|
+
partial: true,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
lastContent = content;
|
|
106
|
+
staleCount = 0;
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
staleCount++;
|
|
110
|
+
if (staleCount >= MAX_STALE_CYCLES) {
|
|
111
|
+
this.emit(processId, {
|
|
112
|
+
id: `${processId}-timeout`,
|
|
113
|
+
processId,
|
|
114
|
+
timestamp: new Date().toISOString(),
|
|
115
|
+
type: 'status_change',
|
|
116
|
+
status: 'stopped',
|
|
117
|
+
reason: 'output stale timeout (120s)',
|
|
118
|
+
});
|
|
119
|
+
this.panes.delete(processId);
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
emit(processId, entry) {
|
|
126
|
+
const cbs = this.listeners.get(processId);
|
|
127
|
+
if (cbs) {
|
|
128
|
+
cbs.forEach(cb => cb(entry));
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=terminal-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-adapter.js","sourceRoot":"","sources":["../../src/agents/terminal-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { type ExecFileOptions } from 'node:child_process';
|
|
2
|
+
/** Common child_process options with windowsHide:true for all calls. */
|
|
3
|
+
export declare function subprocessOpts(cwd?: string): ExecFileOptions;
|
|
4
|
+
export interface CreatePaneOptions {
|
|
5
|
+
cwd: string;
|
|
6
|
+
cmd?: string;
|
|
7
|
+
direction?: 'right' | 'bottom';
|
|
8
|
+
percent?: number;
|
|
9
|
+
parentPaneId?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface TerminalBackend {
|
|
12
|
+
readonly type: 'tmux' | 'wezterm';
|
|
13
|
+
createPane(options: CreatePaneOptions): Promise<string>;
|
|
14
|
+
sendText(paneId: string, text: string): Promise<void>;
|
|
15
|
+
isAlive(paneId: string): Promise<boolean>;
|
|
16
|
+
getText(paneId: string, lines?: number): Promise<string>;
|
|
17
|
+
killPane(paneId: string): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
export declare class TmuxBackend implements TerminalBackend {
|
|
20
|
+
readonly type: "tmux";
|
|
21
|
+
private enterDelay;
|
|
22
|
+
constructor(options?: {
|
|
23
|
+
enterDelayMs?: number;
|
|
24
|
+
});
|
|
25
|
+
createPane(options: CreatePaneOptions): Promise<string>;
|
|
26
|
+
sendText(paneId: string, text: string): Promise<void>;
|
|
27
|
+
isAlive(paneId: string): Promise<boolean>;
|
|
28
|
+
getText(paneId: string, lines?: number): Promise<string>;
|
|
29
|
+
killPane(paneId: string): Promise<void>;
|
|
30
|
+
}
|
|
31
|
+
export declare class WeztermBackend implements TerminalBackend {
|
|
32
|
+
readonly type: "wezterm";
|
|
33
|
+
private enterDelay;
|
|
34
|
+
private weztermBin;
|
|
35
|
+
constructor(options?: {
|
|
36
|
+
enterDelayMs?: number;
|
|
37
|
+
weztermBin?: string;
|
|
38
|
+
});
|
|
39
|
+
createPane(options: CreatePaneOptions): Promise<string>;
|
|
40
|
+
sendText(paneId: string, text: string): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* 3-level Enter key fallback:
|
|
43
|
+
* 1. wezterm cli send-key --key Enter (flag form)
|
|
44
|
+
* 2. wezterm cli send-key Enter (positional form)
|
|
45
|
+
* 3. CR byte via send-text --no-paste (final fallback)
|
|
46
|
+
*/
|
|
47
|
+
private sendEnter;
|
|
48
|
+
isAlive(paneId: string): Promise<boolean>;
|
|
49
|
+
getText(paneId: string, lines?: number): Promise<string>;
|
|
50
|
+
killPane(paneId: string): Promise<void>;
|
|
51
|
+
}
|
|
52
|
+
export declare function detectBackend(): TerminalBackend | null;
|
|
53
|
+
//# sourceMappingURL=terminal-backend.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-backend.d.ts","sourceRoot":"","sources":["../../src/agents/terminal-backend.ts"],"names":[],"mappings":"AAIA,OAAO,EAAY,KAAK,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAuBpE,wEAAwE;AACxE,wBAAgB,cAAc,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,eAAe,CAO5D;AAUD,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACxD,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1C,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACzD,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACzC;AAMD,qBAAa,WAAY,YAAW,eAAe;IACjD,QAAQ,CAAC,IAAI,EAAG,MAAM,CAAU;IAChC,OAAO,CAAC,UAAU,CAAS;gBAEf,OAAO,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE;IAKzC,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC;IAmCvD,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgDrD,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAWzC,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,OAAO,CAAC,MAAM,CAAC;IAQpD,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAO9C;AAMD,qBAAa,cAAe,YAAW,eAAe;IACpD,QAAQ,CAAC,IAAI,EAAG,SAAS,CAAU;IACnC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,UAAU,CAAS;gBAEf,OAAO,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE;IAQ9D,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC;IAyBvD,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA8B3D;;;;;OAKG;YACW,SAAS;IA2BjB,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAoBzC,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,OAAO,CAAC,MAAM,CAAC;IASpD,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAM9C;AAMD,wBAAgB,aAAa,IAAI,eAAe,GAAG,IAAI,CAQtD"}
|