triflux 3.2.0-dev.10 → 3.2.0-dev.11
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/hub/team/orchestrator.mjs +15 -20
- package/hub/team/pane.mjs +21 -10
- package/package.json +1 -1
|
@@ -58,6 +58,8 @@ export function buildLeadPrompt(taskDescription, config) {
|
|
|
58
58
|
|
|
59
59
|
const workerIds = workers.map((w) => w.agentId).join(", ");
|
|
60
60
|
|
|
61
|
+
const bridgePath = "node hub/bridge.mjs";
|
|
62
|
+
|
|
61
63
|
return `리드 에이전트: ${agentId}
|
|
62
64
|
|
|
63
65
|
목표: ${taskDescription}
|
|
@@ -68,14 +70,13 @@ ${roster}
|
|
|
68
70
|
|
|
69
71
|
규칙:
|
|
70
72
|
- 가능한 짧고 핵심만 지시/요약(토큰 절약)
|
|
71
|
-
- 워커
|
|
72
|
-
|
|
73
|
+
- 워커 제어:
|
|
74
|
+
${bridgePath} result --agent ${agentId} --topic lead.control
|
|
73
75
|
- 워커 결과 수집:
|
|
74
|
-
|
|
76
|
+
${bridgePath} context --agent ${agentId} --max 20
|
|
75
77
|
- 최종 결과는 topic="task.result"를 모아 통합
|
|
76
78
|
|
|
77
|
-
|
|
78
|
-
Hub: ${hubUrl}
|
|
79
|
+
워커 ID: ${workerIds || "(없음)"}
|
|
79
80
|
지금 즉시 워커를 배정하고 병렬 진행을 관리하라.`;
|
|
80
81
|
}
|
|
81
82
|
|
|
@@ -93,26 +94,20 @@ export function buildPrompt(subtask, config) {
|
|
|
93
94
|
|
|
94
95
|
const hubBase = hubUrl.replace("/mcp", "");
|
|
95
96
|
|
|
97
|
+
const bridgePath = "node hub/bridge.mjs";
|
|
98
|
+
|
|
96
99
|
return `워커: ${agentId} (${cli})
|
|
97
100
|
작업: ${subtask}
|
|
98
101
|
|
|
99
102
|
필수 규칙:
|
|
100
103
|
1) 간결하게 작업(불필요한 장문 설명 금지)
|
|
101
|
-
2) 시작 즉시
|
|
102
|
-
register
|
|
104
|
+
2) 시작 즉시 등록:
|
|
105
|
+
${bridgePath} register --agent ${agentId} --cli ${cli} --topics lead.control,task.result
|
|
103
106
|
3) 주기적으로 수신함 확인:
|
|
104
|
-
|
|
105
|
-
4) lead.control 수신 시 즉시 반응
|
|
106
|
-
- interrupt: 즉시 중단, 진행상태 요약 publish
|
|
107
|
-
- stop: 작업 종료, 최종 요약 publish 후 대기
|
|
108
|
-
- pause: 작업 일시정지
|
|
109
|
-
- resume: 작업 재개
|
|
107
|
+
${bridgePath} context --agent ${agentId} --max 10
|
|
108
|
+
4) lead.control 수신 시 즉시 반응 (interrupt/stop/pause/resume)
|
|
110
109
|
5) 완료 시 결과 발행:
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
MCP가 없으면 REST 폴백:
|
|
114
|
-
- POST ${hubBase}/bridge/register
|
|
115
|
-
- POST ${hubBase}/bridge/result
|
|
110
|
+
${bridgePath} result --agent ${agentId} --topic task.result --file <출력파일>
|
|
116
111
|
|
|
117
112
|
지금 작업을 시작하라.`;
|
|
118
113
|
}
|
|
@@ -149,7 +144,7 @@ export async function orchestrate(sessionName, assignments, opts = {}) {
|
|
|
149
144
|
teammateMode,
|
|
150
145
|
workers: workers.map((w) => ({ agentId: w.agentId, cli: w.cli, subtask: w.subtask })),
|
|
151
146
|
});
|
|
152
|
-
injectPrompt(lead.target, leadPrompt);
|
|
147
|
+
injectPrompt(lead.target, leadPrompt, { useFileRef: true });
|
|
153
148
|
await new Promise((r) => setTimeout(r, 100));
|
|
154
149
|
}
|
|
155
150
|
|
|
@@ -160,7 +155,7 @@ export async function orchestrate(sessionName, assignments, opts = {}) {
|
|
|
160
155
|
hubUrl,
|
|
161
156
|
sessionName,
|
|
162
157
|
});
|
|
163
|
-
injectPrompt(worker.target, prompt);
|
|
158
|
+
injectPrompt(worker.target, prompt, { useFileRef: true });
|
|
164
159
|
await new Promise((r) => setTimeout(r, 100));
|
|
165
160
|
}
|
|
166
161
|
}
|
package/hub/team/pane.mjs
CHANGED
|
@@ -92,19 +92,35 @@ export function startCliInPane(target, command) {
|
|
|
92
92
|
* @param {string} target — 예: tfx-multi-abc:0.1
|
|
93
93
|
* @param {string} prompt — 주입할 텍스트
|
|
94
94
|
*/
|
|
95
|
-
|
|
96
|
-
|
|
95
|
+
/**
|
|
96
|
+
* pane에 프롬프트 주입
|
|
97
|
+
* @param {string} target — 예: tfx-multi-abc:0.1
|
|
98
|
+
* @param {string} prompt — 주입할 텍스트
|
|
99
|
+
* @param {object} [opts]
|
|
100
|
+
* @param {boolean} [opts.useFileRef] — true면 TUI용 @file 참조 방식 (psmux 전용)
|
|
101
|
+
*/
|
|
102
|
+
export function injectPrompt(target, prompt, { useFileRef = false } = {}) {
|
|
97
103
|
const tmpDir = join(tmpdir(), "tfx-multi");
|
|
98
104
|
mkdirSync(tmpDir, { recursive: true });
|
|
99
105
|
|
|
100
|
-
// pane ID를 파일명에 포함 (충돌 방지)
|
|
101
106
|
const safeTarget = target.replace(/[:.]/g, "-");
|
|
102
107
|
const tmpFile = join(tmpDir, `prompt-${safeTarget}-${Date.now()}.txt`);
|
|
103
108
|
|
|
109
|
+
// psmux + TUI 앱: @file 참조로 주입 (paste-buffer는 TUI와 호환 안 됨)
|
|
110
|
+
if (detectMultiplexer() === "psmux" && useFileRef) {
|
|
111
|
+
writeFileSync(tmpFile, prompt, "utf8");
|
|
112
|
+
const filePath = tmpFile.replace(/\\/g, "/");
|
|
113
|
+
psmuxExec(["select-pane", "-t", target]);
|
|
114
|
+
psmuxExec(["send-keys", "-t", target, "-l", `@${filePath}`]);
|
|
115
|
+
psmuxExec(["send-keys", "-t", target, "Enter"]);
|
|
116
|
+
// TUI가 파일을 읽을 시간을 주고 정리
|
|
117
|
+
setTimeout(() => { try { unlinkSync(tmpFile); } catch {} }, 10000);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
104
121
|
try {
|
|
105
122
|
writeFileSync(tmpFile, prompt, "utf8");
|
|
106
123
|
|
|
107
|
-
// psmux는 buffer 명령에 세션 컨텍스트가 필요하다.
|
|
108
124
|
if (detectMultiplexer() === "psmux") {
|
|
109
125
|
const sessionName = getPsmuxSessionName(target);
|
|
110
126
|
psmuxExec(["load-buffer", "-t", sessionName, toMuxPath(tmpFile)]);
|
|
@@ -119,12 +135,7 @@ export function injectPrompt(target, prompt) {
|
|
|
119
135
|
muxExec(`paste-buffer -t ${target}`);
|
|
120
136
|
muxExec(`send-keys -t ${target} Enter`);
|
|
121
137
|
} finally {
|
|
122
|
-
|
|
123
|
-
try {
|
|
124
|
-
unlinkSync(tmpFile);
|
|
125
|
-
} catch {
|
|
126
|
-
// 정리 실패 무시
|
|
127
|
-
}
|
|
138
|
+
try { unlinkSync(tmpFile); } catch {}
|
|
128
139
|
}
|
|
129
140
|
}
|
|
130
141
|
|