@triflux/remote 10.1.0 → 10.26.0
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 +2179 -709
- 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 +78 -17
- package/hub/team/build-worker-prompt.mjs +73 -0
- package/hub/team/check-mcp-hub.mjs +49 -0
- package/hub/team/claude-daemon-control.mjs +1130 -0
- package/hub/team/claude-native-bridge.mjs +1011 -0
- package/hub/team/claude-session-projection.mjs +74 -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 +151 -33
- package/hub/team/cli/commands/start/parse-args.mjs +97 -13
- package/hub/team/cli/commands/start/start-headless.mjs +155 -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/help.mjs +1 -1
- 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 +61 -4
- 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 +256 -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 +2213 -1156
- package/hub/team/health-probe.mjs +232 -69
- package/hub/team/interactive-native-launcher.mjs +106 -0
- package/hub/team/interactive-native-worker.mjs +80 -0
- package/hub/team/interactive-tui-transport.mjs +465 -0
- package/hub/team/launcher-template.mjs +49 -17
- 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 +120 -42
- 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 -20
- package/hub/team/process-cleanup.mjs +69 -25
- package/hub/team/psmux.mjs +1022 -281
- 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 +336 -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 +574 -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 +1544 -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 +319 -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 +292 -0
- package/hub/team/tui-lite.mjs +237 -148
- package/hub/team/tui-remote-adapter.mjs +18 -34
- package/hub/team/tui-synapse.mjs +223 -0
- package/hub/team/tui-viewer.mjs +108 -48
- package/hub/team/tui-widgets.mjs +262 -0
- package/hub/team/tui.mjs +931 -439
- package/hub/team/worker-completion-validator.mjs +84 -0
- package/hub/team/worker-sandbox.mjs +97 -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 +477 -252
- package/hub/tray.mjs +411 -368
- package/hub/workers/antigravity-route-worker.mjs +169 -0
- 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 +570 -499
- package/hub/workers/factory.mjs +103 -21
- package/hub/workers/gemini-worker.mjs +126 -284
- package/hub/workers/interface.mjs +24 -2
- package/hub/workers/lib/jsonrpc-stdio.mjs +463 -0
- package/hub/workers/worker-utils.mjs +23 -17
- 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 +37 -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-health-check.mjs +159 -0
- package/scripts/lib/mcp-gateway-servers.mjs +70 -0
- package/scripts/lib/mcp-gateway-wrapper-check.mjs +35 -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 +224 -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
|
+
}
|