@triflux/remote 10.1.0 → 10.25.1
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/pipe.mjs +239 -121
- package/hub/public/dashboard.html +61 -0
- package/hub/server.mjs +2165 -708
- package/hub/store-adapter.mjs +59 -26
- package/hub/store.mjs +356 -153
- package/hub/team/agent-map.json +26 -7
- package/hub/team/ansi.mjs +245 -146
- package/hub/team/backend.mjs +84 -17
- package/hub/team/build-worker-prompt.mjs +42 -0
- package/hub/team/check-mcp-hub.mjs +49 -0
- package/hub/team/claude-daemon-control.mjs +219 -0
- package/hub/team/claude-native-bridge.mjs +784 -0
- package/hub/team/claude-session-projection.mjs +65 -0
- package/hub/team/cli/commands/attach.mjs +57 -37
- package/hub/team/cli/commands/control.mjs +29 -8
- package/hub/team/cli/commands/debug.mjs +95 -74
- package/hub/team/cli/commands/focus.mjs +80 -53
- package/hub/team/cli/commands/interrupt.mjs +18 -6
- package/hub/team/cli/commands/kill.mjs +16 -5
- package/hub/team/cli/commands/list.mjs +31 -24
- package/hub/team/cli/commands/send.mjs +19 -6
- package/hub/team/cli/commands/start/index.mjs +154 -33
- package/hub/team/cli/commands/start/parse-args.mjs +89 -12
- package/hub/team/cli/commands/start/start-headless.mjs +125 -37
- package/hub/team/cli/commands/start/start-in-process.mjs +50 -40
- package/hub/team/cli/commands/start/start-mux.mjs +122 -73
- package/hub/team/cli/commands/start/start-wt.mjs +86 -69
- package/hub/team/cli/commands/status.mjs +43 -14
- package/hub/team/cli/commands/stop.mjs +11 -4
- package/hub/team/cli/commands/task.mjs +8 -3
- package/hub/team/cli/commands/tasks.mjs +13 -13
- package/hub/team/cli/index.mjs +2 -2
- package/hub/team/cli/manifest.mjs +38 -8
- package/hub/team/cli/render.mjs +52 -30
- package/hub/team/cli/services/attach-fallback.mjs +74 -54
- package/hub/team/cli/services/hub-client.mjs +44 -16
- package/hub/team/cli/services/member-selector.mjs +37 -30
- package/hub/team/cli/services/native-control.mjs +144 -116
- package/hub/team/cli/services/runtime-mode.mjs +55 -1
- package/hub/team/cli/services/state-store.mjs +66 -9
- package/hub/team/cli/services/task-model.mjs +40 -30
- package/hub/team/codex-review.mjs +521 -0
- package/hub/team/conductor-mesh-bridge.mjs +25 -24
- package/hub/team/conductor-registry.mjs +121 -0
- package/hub/team/conductor.mjs +1379 -671
- package/hub/team/consensus-meta.mjs +176 -0
- package/hub/team/dashboard-anchor.mjs +4 -5
- package/hub/team/dashboard-layout.mjs +3 -1
- package/hub/team/dashboard-open.mjs +20 -118
- package/hub/team/dashboard.mjs +76 -28
- package/hub/team/event-log.mjs +18 -10
- package/hub/team/execution-mode.mjs +241 -0
- package/hub/team/extract-completion-payload.mjs +110 -0
- package/hub/team/git-preflight.mjs +286 -0
- package/hub/team/handoff.mjs +49 -18
- package/hub/team/headless-bridge-session.mjs +17 -0
- package/hub/team/headless.mjs +2065 -1156
- package/hub/team/health-probe.mjs +232 -69
- package/hub/team/launcher-template.mjs +23 -13
- package/hub/team/lead-control.mjs +91 -4
- package/hub/team/mcp-selector.mjs +145 -0
- package/hub/team/native-supervisor.mjs +90 -26
- package/hub/team/native.mjs +74 -35
- package/hub/team/nativeProxy.mjs +184 -113
- package/hub/team/notify.mjs +147 -78
- package/hub/team/orchestrator.mjs +173 -161
- package/hub/team/pane.mjs +43 -15
- package/hub/team/process-cleanup.mjs +69 -25
- package/hub/team/psmux.mjs +1020 -279
- package/hub/team/recovery-store.mjs +149 -0
- package/hub/team/remote-probe.mjs +68 -52
- package/hub/team/remote-session.mjs +131 -59
- package/hub/team/remote-watcher.mjs +61 -33
- package/hub/team/retry-state-machine.mjs +267 -0
- package/hub/team/routing.mjs +51 -25
- package/hub/team/runtime-strategy.mjs +200 -0
- package/hub/team/schemas/worker-completion.json +39 -0
- package/hub/team/sentinel-capture.mjs +127 -0
- package/hub/team/session-sync.mjs +153 -6
- package/hub/team/session.mjs +605 -611
- package/hub/team/shared.mjs +13 -13
- package/hub/team/staleState.mjs +72 -30
- package/hub/team/swarm-cli.mjs +390 -0
- package/hub/team/swarm-hypervisor.mjs +1522 -193
- package/hub/team/swarm-intent.mjs +216 -0
- package/hub/team/swarm-locks.mjs +140 -25
- package/hub/team/swarm-planner.mjs +121 -21
- package/hub/team/swarm-preflight.mjs +317 -0
- package/hub/team/swarm-reconciler.mjs +128 -23
- package/hub/team/synapse-cli.mjs +458 -0
- package/hub/team/synapse-http.mjs +60 -0
- package/hub/team/synapse-registry.mjs +329 -0
- package/hub/team/terminal-opener.mjs +216 -0
- package/hub/team/tui-core.mjs +288 -0
- package/hub/team/tui-lite.mjs +234 -146
- package/hub/team/tui-remote-adapter.mjs +18 -34
- package/hub/team/tui-synapse.mjs +223 -0
- package/hub/team/tui-viewer.mjs +104 -44
- package/hub/team/tui-widgets.mjs +262 -0
- package/hub/team/tui.mjs +927 -437
- package/hub/team/worker-completion-validator.mjs +84 -0
- package/hub/team/worker-sandbox.mjs +93 -0
- package/hub/team/worker-signal.mjs +263 -0
- package/hub/team/worker-signal.types.d.ts +52 -0
- package/hub/team/worktree-lifecycle.mjs +517 -63
- package/hub/team/wt-manager.mjs +297 -26
- package/hub/tools.mjs +474 -252
- package/hub/tray.mjs +411 -368
- package/hub/workers/claude-worker.mjs +162 -118
- package/hub/workers/codex-app-server-worker.mjs +1015 -0
- package/hub/workers/codex-mcp.mjs +724 -507
- package/hub/workers/delegator-mcp.mjs +662 -335
- package/hub/workers/factory.mjs +100 -21
- package/hub/workers/gemini-worker.mjs +179 -86
- package/hub/workers/interface.mjs +23 -2
- package/hub/workers/lib/jsonrpc-stdio.mjs +463 -0
- package/hub/workers/worker-utils.mjs +22 -16
- package/package.json +4 -3
- package/scripts/lib/agent-json.mjs +27 -0
- package/scripts/lib/async.mjs +174 -0
- package/scripts/lib/claudemd-scanner.mjs +223 -0
- package/scripts/lib/cli-agy.mjs +62 -0
- package/scripts/lib/cli-claude.mjs +78 -0
- package/scripts/lib/cli-codex.mjs +199 -0
- package/scripts/lib/cli-gemini.mjs +67 -0
- package/scripts/lib/codex-recovery.sh +50 -0
- package/scripts/lib/context.mjs +67 -0
- package/scripts/lib/cross-review-utils.mjs +59 -0
- package/scripts/lib/doctor-env-checks.mjs +121 -0
- package/scripts/lib/dynamic-route-cli.mjs +107 -0
- package/scripts/lib/env-probe.mjs +269 -0
- package/scripts/lib/env.mjs +14 -0
- package/scripts/lib/gemini-profiles.mjs +119 -0
- package/scripts/lib/handoff.mjs +187 -0
- package/scripts/lib/hook-utils.mjs +16 -0
- package/scripts/lib/hub.mjs +48 -0
- package/scripts/lib/keyword-rules.mjs +195 -0
- package/scripts/lib/logger.mjs +105 -0
- package/scripts/lib/mcp-filter.mjs +883 -0
- package/scripts/lib/mcp-gateway-servers.mjs +70 -0
- package/scripts/lib/mcp-guard-engine.mjs +2120 -0
- package/scripts/lib/mcp-health.mjs +773 -0
- package/scripts/lib/mcp-manifest.mjs +89 -0
- package/scripts/lib/mcp-server-catalog.mjs +355 -0
- package/scripts/lib/pid.mjs +63 -0
- package/scripts/lib/process-utils.mjs +26 -0
- package/scripts/lib/psmux-info.mjs +179 -0
- package/scripts/lib/quota.mjs +47 -0
- package/scripts/lib/remote-spawn-transfer.mjs +226 -0
- package/scripts/lib/skill-state.mjs +220 -0
- package/scripts/lib/skill-template.mjs +375 -0
- package/scripts/lib/team.mjs +75 -0
- package/scripts/lib/timeout.mjs +66 -0
- package/scripts/lib/tmp.mjs +26 -0
- package/scripts/lib/toml.mjs +113 -0
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
// hub/team/tui-widgets.mjs — UX 리뉴얼 위젯 (ISSUE-14)
|
|
2
|
+
// k9s/lazygit/btop 스타일 위젯: 스파크라인, 검색, 패널 리사이즈
|
|
3
|
+
|
|
4
|
+
import { color, dim, MOCHA } from "./ansi.mjs";
|
|
5
|
+
|
|
6
|
+
// ── 스파크라인 ────────────────────────────────────────────────────────────
|
|
7
|
+
// Unicode block elements for sparkline rendering
|
|
8
|
+
const SPARK_CHARS = "▁▂▃▄▅▆▇█";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 토큰 소비 추이를 미니 스파크라인으로 렌더링
|
|
12
|
+
* @param {number[]} values - 시계열 값 배열
|
|
13
|
+
* @param {number} [width=8] - 표시 폭 (문자 수)
|
|
14
|
+
* @param {string} [fg] - ANSI 색상 시퀀스
|
|
15
|
+
* @returns {string} 스파크라인 문자열
|
|
16
|
+
*/
|
|
17
|
+
export function sparkline(values, width = 8, fg = MOCHA.executing) {
|
|
18
|
+
if (!values || values.length === 0) return dim("─".repeat(width));
|
|
19
|
+
|
|
20
|
+
// 최근 width개만 사용
|
|
21
|
+
const data = values.slice(-width);
|
|
22
|
+
const min = Math.min(...data);
|
|
23
|
+
const max = Math.max(...data);
|
|
24
|
+
const range = max - min || 1;
|
|
25
|
+
|
|
26
|
+
const chars = data.map((v) => {
|
|
27
|
+
const idx = Math.round(((v - min) / range) * (SPARK_CHARS.length - 1));
|
|
28
|
+
return SPARK_CHARS[idx];
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// width보다 짧으면 왼쪽 패딩
|
|
32
|
+
const pad = width - chars.length;
|
|
33
|
+
const padStr = pad > 0 ? dim("─".repeat(pad)) : "";
|
|
34
|
+
return padStr + color(chars.join(""), fg);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* 워커별 토큰 히스토리 추적기
|
|
39
|
+
* @param {number} [maxSamples=16] - 최대 샘플 수
|
|
40
|
+
*/
|
|
41
|
+
export function createTokenTracker(maxSamples = 16) {
|
|
42
|
+
const histories = new Map();
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
/** 워커의 토큰 값을 기록 */
|
|
46
|
+
record(workerName, tokens) {
|
|
47
|
+
if (tokens === null || tokens === undefined || tokens === "") return;
|
|
48
|
+
const numValue =
|
|
49
|
+
typeof tokens === "number" ? tokens : parseFloat(String(tokens));
|
|
50
|
+
if (!Number.isFinite(numValue)) return;
|
|
51
|
+
|
|
52
|
+
let history = histories.get(workerName);
|
|
53
|
+
if (!history) {
|
|
54
|
+
history = [];
|
|
55
|
+
histories.set(workerName, history);
|
|
56
|
+
}
|
|
57
|
+
history.push(numValue);
|
|
58
|
+
if (history.length > maxSamples) history.shift();
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
/** 워커의 스파크라인 반환 */
|
|
62
|
+
sparkline(workerName, width = 8) {
|
|
63
|
+
const history = histories.get(workerName);
|
|
64
|
+
return sparkline(history, width);
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
/** 워커의 히스토리 반환 */
|
|
68
|
+
getHistory(workerName) {
|
|
69
|
+
return histories.get(workerName) || [];
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
clear() {
|
|
73
|
+
histories.clear();
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// ── 검색 (/ + n/N) ───────────────────────────────────────────────────────
|
|
79
|
+
/**
|
|
80
|
+
* 인라인 검색 상태 관리자
|
|
81
|
+
* vim 스타일 / 검색 + n(다음)/N(이전) 탐색
|
|
82
|
+
*/
|
|
83
|
+
export function createSearchState() {
|
|
84
|
+
let query = "";
|
|
85
|
+
let isActive = false;
|
|
86
|
+
let inputBuffer = "";
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
/** 검색 모드 활성화 */
|
|
90
|
+
activate() {
|
|
91
|
+
isActive = true;
|
|
92
|
+
inputBuffer = "";
|
|
93
|
+
query = "";
|
|
94
|
+
},
|
|
95
|
+
|
|
96
|
+
/** 검색 모드 비활성화 */
|
|
97
|
+
deactivate() {
|
|
98
|
+
isActive = false;
|
|
99
|
+
inputBuffer = "";
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
/** 현재 검색 활성 여부 */
|
|
103
|
+
get active() {
|
|
104
|
+
return isActive;
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
/** 현재 쿼리 */
|
|
108
|
+
get query() {
|
|
109
|
+
return query;
|
|
110
|
+
},
|
|
111
|
+
|
|
112
|
+
/** 입력 버퍼 (검색 모드 중 타이핑) */
|
|
113
|
+
get buffer() {
|
|
114
|
+
return inputBuffer;
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
/** 키 입력 처리. true 반환 시 해당 키를 소비함 */
|
|
118
|
+
handleKey(key) {
|
|
119
|
+
if (!isActive) return false;
|
|
120
|
+
|
|
121
|
+
// Enter: 검색 확정
|
|
122
|
+
if (key === "\r" || key === "\n") {
|
|
123
|
+
query = inputBuffer;
|
|
124
|
+
isActive = false;
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Escape: 검색 취소
|
|
129
|
+
if (key === "\x1b") {
|
|
130
|
+
this.deactivate();
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Backspace
|
|
135
|
+
if (key === "\x7f" || key === "\b") {
|
|
136
|
+
inputBuffer = inputBuffer.slice(0, -1);
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Ctrl+C: 취소
|
|
141
|
+
if (key === "\u0003") {
|
|
142
|
+
this.deactivate();
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// 일반 문자
|
|
147
|
+
if (key.length === 1 && key >= " ") {
|
|
148
|
+
inputBuffer += key;
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return true; // 검색 모드 중 다른 키는 무시
|
|
153
|
+
},
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* 이름 목록에서 쿼리와 매칭되는 인덱스 찾기
|
|
157
|
+
* @param {string[]} names - 워커 이름 배열
|
|
158
|
+
* @param {number} currentIdx - 현재 선택 인덱스
|
|
159
|
+
* @param {number} direction - 1(다음) 또는 -1(이전)
|
|
160
|
+
* @returns {number} 매칭 인덱스 또는 -1
|
|
161
|
+
*/
|
|
162
|
+
findMatch(names, currentIdx, direction = 1) {
|
|
163
|
+
if (!query || names.length === 0) return -1;
|
|
164
|
+
const q = query.toLowerCase();
|
|
165
|
+
const len = names.length;
|
|
166
|
+
for (let i = 1; i <= len; i++) {
|
|
167
|
+
const idx = (currentIdx + i * direction + len) % len;
|
|
168
|
+
if (names[idx].toLowerCase().includes(q)) return idx;
|
|
169
|
+
}
|
|
170
|
+
return -1;
|
|
171
|
+
},
|
|
172
|
+
|
|
173
|
+
/** 검색 프롬프트 렌더링 */
|
|
174
|
+
renderPrompt(width) {
|
|
175
|
+
if (!isActive) {
|
|
176
|
+
if (query) return dim(` /${query}`);
|
|
177
|
+
return "";
|
|
178
|
+
}
|
|
179
|
+
const prompt = `/${inputBuffer}`;
|
|
180
|
+
const cursor = "█";
|
|
181
|
+
return color(prompt + cursor, MOCHA.blue);
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// ── 패널 리사이즈 (H/L) ──────────────────────────────────────────────────
|
|
187
|
+
/**
|
|
188
|
+
* 패널 비율 관리자
|
|
189
|
+
* H: rail 축소, L: rail 확대 (k9s 스타일)
|
|
190
|
+
*/
|
|
191
|
+
export function createPanelResizer(opts = {}) {
|
|
192
|
+
const { minRatio = 0.15, maxRatio = 0.5, step = 0.05 } = opts;
|
|
193
|
+
let railRatio = opts.initialRatio || 0.3;
|
|
194
|
+
|
|
195
|
+
return {
|
|
196
|
+
get ratio() {
|
|
197
|
+
return railRatio;
|
|
198
|
+
},
|
|
199
|
+
|
|
200
|
+
/** rail 비율 축소 (H) — detail 패널 확대 */
|
|
201
|
+
shrinkRail() {
|
|
202
|
+
railRatio = Math.max(minRatio, railRatio - step);
|
|
203
|
+
return railRatio;
|
|
204
|
+
},
|
|
205
|
+
|
|
206
|
+
/** rail 비율 확대 (L) — detail 패널 축소 */
|
|
207
|
+
expandRail() {
|
|
208
|
+
railRatio = Math.min(maxRatio, railRatio + step);
|
|
209
|
+
return railRatio;
|
|
210
|
+
},
|
|
211
|
+
|
|
212
|
+
/** 비율 리셋 */
|
|
213
|
+
reset() {
|
|
214
|
+
railRatio = opts.initialRatio || 0.3;
|
|
215
|
+
return railRatio;
|
|
216
|
+
},
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// ── vim 모션 헬퍼 ─────────────────────────────────────────────────────────
|
|
221
|
+
/**
|
|
222
|
+
* gg/G 모션을 위한 키 시퀀스 감지
|
|
223
|
+
* 두 번 연속 'g'를 누르면 gg (첫 번째 항목으로 이동)
|
|
224
|
+
*/
|
|
225
|
+
export function createVimMotion() {
|
|
226
|
+
let lastKey = "";
|
|
227
|
+
let lastKeyTime = 0;
|
|
228
|
+
const DOUBLE_TAP_MS = 500;
|
|
229
|
+
|
|
230
|
+
return {
|
|
231
|
+
/**
|
|
232
|
+
* 키 입력 처리
|
|
233
|
+
* @returns {"gg"|"G"|null} 감지된 모션 또는 null
|
|
234
|
+
*/
|
|
235
|
+
handleKey(key) {
|
|
236
|
+
const now = Date.now();
|
|
237
|
+
|
|
238
|
+
if (key === "g") {
|
|
239
|
+
if (lastKey === "g" && now - lastKeyTime < DOUBLE_TAP_MS) {
|
|
240
|
+
lastKey = "";
|
|
241
|
+
return "gg"; // 첫 번째 항목으로
|
|
242
|
+
}
|
|
243
|
+
lastKey = "g";
|
|
244
|
+
lastKeyTime = now;
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (key === "G") {
|
|
249
|
+
lastKey = "";
|
|
250
|
+
return "G"; // 마지막 항목으로
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
lastKey = "";
|
|
254
|
+
return null;
|
|
255
|
+
},
|
|
256
|
+
|
|
257
|
+
reset() {
|
|
258
|
+
lastKey = "";
|
|
259
|
+
lastKeyTime = 0;
|
|
260
|
+
},
|
|
261
|
+
};
|
|
262
|
+
}
|