@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.
Files changed (155) hide show
  1. package/hub/pipe.mjs +239 -121
  2. package/hub/public/dashboard.html +61 -0
  3. package/hub/server.mjs +2165 -708
  4. package/hub/store-adapter.mjs +59 -26
  5. package/hub/store.mjs +356 -153
  6. package/hub/team/agent-map.json +26 -7
  7. package/hub/team/ansi.mjs +245 -146
  8. package/hub/team/backend.mjs +84 -17
  9. package/hub/team/build-worker-prompt.mjs +42 -0
  10. package/hub/team/check-mcp-hub.mjs +49 -0
  11. package/hub/team/claude-daemon-control.mjs +219 -0
  12. package/hub/team/claude-native-bridge.mjs +784 -0
  13. package/hub/team/claude-session-projection.mjs +65 -0
  14. package/hub/team/cli/commands/attach.mjs +57 -37
  15. package/hub/team/cli/commands/control.mjs +29 -8
  16. package/hub/team/cli/commands/debug.mjs +95 -74
  17. package/hub/team/cli/commands/focus.mjs +80 -53
  18. package/hub/team/cli/commands/interrupt.mjs +18 -6
  19. package/hub/team/cli/commands/kill.mjs +16 -5
  20. package/hub/team/cli/commands/list.mjs +31 -24
  21. package/hub/team/cli/commands/send.mjs +19 -6
  22. package/hub/team/cli/commands/start/index.mjs +154 -33
  23. package/hub/team/cli/commands/start/parse-args.mjs +89 -12
  24. package/hub/team/cli/commands/start/start-headless.mjs +125 -37
  25. package/hub/team/cli/commands/start/start-in-process.mjs +50 -40
  26. package/hub/team/cli/commands/start/start-mux.mjs +122 -73
  27. package/hub/team/cli/commands/start/start-wt.mjs +86 -69
  28. package/hub/team/cli/commands/status.mjs +43 -14
  29. package/hub/team/cli/commands/stop.mjs +11 -4
  30. package/hub/team/cli/commands/task.mjs +8 -3
  31. package/hub/team/cli/commands/tasks.mjs +13 -13
  32. package/hub/team/cli/index.mjs +2 -2
  33. package/hub/team/cli/manifest.mjs +38 -8
  34. package/hub/team/cli/render.mjs +52 -30
  35. package/hub/team/cli/services/attach-fallback.mjs +74 -54
  36. package/hub/team/cli/services/hub-client.mjs +44 -16
  37. package/hub/team/cli/services/member-selector.mjs +37 -30
  38. package/hub/team/cli/services/native-control.mjs +144 -116
  39. package/hub/team/cli/services/runtime-mode.mjs +55 -1
  40. package/hub/team/cli/services/state-store.mjs +66 -9
  41. package/hub/team/cli/services/task-model.mjs +40 -30
  42. package/hub/team/codex-review.mjs +521 -0
  43. package/hub/team/conductor-mesh-bridge.mjs +25 -24
  44. package/hub/team/conductor-registry.mjs +121 -0
  45. package/hub/team/conductor.mjs +1379 -671
  46. package/hub/team/consensus-meta.mjs +176 -0
  47. package/hub/team/dashboard-anchor.mjs +4 -5
  48. package/hub/team/dashboard-layout.mjs +3 -1
  49. package/hub/team/dashboard-open.mjs +20 -118
  50. package/hub/team/dashboard.mjs +76 -28
  51. package/hub/team/event-log.mjs +18 -10
  52. package/hub/team/execution-mode.mjs +241 -0
  53. package/hub/team/extract-completion-payload.mjs +110 -0
  54. package/hub/team/git-preflight.mjs +286 -0
  55. package/hub/team/handoff.mjs +49 -18
  56. package/hub/team/headless-bridge-session.mjs +17 -0
  57. package/hub/team/headless.mjs +2065 -1156
  58. package/hub/team/health-probe.mjs +232 -69
  59. package/hub/team/launcher-template.mjs +23 -13
  60. package/hub/team/lead-control.mjs +91 -4
  61. package/hub/team/mcp-selector.mjs +145 -0
  62. package/hub/team/native-supervisor.mjs +90 -26
  63. package/hub/team/native.mjs +74 -35
  64. package/hub/team/nativeProxy.mjs +184 -113
  65. package/hub/team/notify.mjs +147 -78
  66. package/hub/team/orchestrator.mjs +173 -161
  67. package/hub/team/pane.mjs +43 -15
  68. package/hub/team/process-cleanup.mjs +69 -25
  69. package/hub/team/psmux.mjs +1020 -279
  70. package/hub/team/recovery-store.mjs +149 -0
  71. package/hub/team/remote-probe.mjs +68 -52
  72. package/hub/team/remote-session.mjs +131 -59
  73. package/hub/team/remote-watcher.mjs +61 -33
  74. package/hub/team/retry-state-machine.mjs +267 -0
  75. package/hub/team/routing.mjs +51 -25
  76. package/hub/team/runtime-strategy.mjs +200 -0
  77. package/hub/team/schemas/worker-completion.json +39 -0
  78. package/hub/team/sentinel-capture.mjs +127 -0
  79. package/hub/team/session-sync.mjs +153 -6
  80. package/hub/team/session.mjs +605 -611
  81. package/hub/team/shared.mjs +13 -13
  82. package/hub/team/staleState.mjs +72 -30
  83. package/hub/team/swarm-cli.mjs +390 -0
  84. package/hub/team/swarm-hypervisor.mjs +1522 -193
  85. package/hub/team/swarm-intent.mjs +216 -0
  86. package/hub/team/swarm-locks.mjs +140 -25
  87. package/hub/team/swarm-planner.mjs +121 -21
  88. package/hub/team/swarm-preflight.mjs +317 -0
  89. package/hub/team/swarm-reconciler.mjs +128 -23
  90. package/hub/team/synapse-cli.mjs +458 -0
  91. package/hub/team/synapse-http.mjs +60 -0
  92. package/hub/team/synapse-registry.mjs +329 -0
  93. package/hub/team/terminal-opener.mjs +216 -0
  94. package/hub/team/tui-core.mjs +288 -0
  95. package/hub/team/tui-lite.mjs +234 -146
  96. package/hub/team/tui-remote-adapter.mjs +18 -34
  97. package/hub/team/tui-synapse.mjs +223 -0
  98. package/hub/team/tui-viewer.mjs +104 -44
  99. package/hub/team/tui-widgets.mjs +262 -0
  100. package/hub/team/tui.mjs +927 -437
  101. package/hub/team/worker-completion-validator.mjs +84 -0
  102. package/hub/team/worker-sandbox.mjs +93 -0
  103. package/hub/team/worker-signal.mjs +263 -0
  104. package/hub/team/worker-signal.types.d.ts +52 -0
  105. package/hub/team/worktree-lifecycle.mjs +517 -63
  106. package/hub/team/wt-manager.mjs +297 -26
  107. package/hub/tools.mjs +474 -252
  108. package/hub/tray.mjs +411 -368
  109. package/hub/workers/claude-worker.mjs +162 -118
  110. package/hub/workers/codex-app-server-worker.mjs +1015 -0
  111. package/hub/workers/codex-mcp.mjs +724 -507
  112. package/hub/workers/delegator-mcp.mjs +662 -335
  113. package/hub/workers/factory.mjs +100 -21
  114. package/hub/workers/gemini-worker.mjs +179 -86
  115. package/hub/workers/interface.mjs +23 -2
  116. package/hub/workers/lib/jsonrpc-stdio.mjs +463 -0
  117. package/hub/workers/worker-utils.mjs +22 -16
  118. package/package.json +4 -3
  119. package/scripts/lib/agent-json.mjs +27 -0
  120. package/scripts/lib/async.mjs +174 -0
  121. package/scripts/lib/claudemd-scanner.mjs +223 -0
  122. package/scripts/lib/cli-agy.mjs +62 -0
  123. package/scripts/lib/cli-claude.mjs +78 -0
  124. package/scripts/lib/cli-codex.mjs +199 -0
  125. package/scripts/lib/cli-gemini.mjs +67 -0
  126. package/scripts/lib/codex-recovery.sh +50 -0
  127. package/scripts/lib/context.mjs +67 -0
  128. package/scripts/lib/cross-review-utils.mjs +59 -0
  129. package/scripts/lib/doctor-env-checks.mjs +121 -0
  130. package/scripts/lib/dynamic-route-cli.mjs +107 -0
  131. package/scripts/lib/env-probe.mjs +269 -0
  132. package/scripts/lib/env.mjs +14 -0
  133. package/scripts/lib/gemini-profiles.mjs +119 -0
  134. package/scripts/lib/handoff.mjs +187 -0
  135. package/scripts/lib/hook-utils.mjs +16 -0
  136. package/scripts/lib/hub.mjs +48 -0
  137. package/scripts/lib/keyword-rules.mjs +195 -0
  138. package/scripts/lib/logger.mjs +105 -0
  139. package/scripts/lib/mcp-filter.mjs +883 -0
  140. package/scripts/lib/mcp-gateway-servers.mjs +70 -0
  141. package/scripts/lib/mcp-guard-engine.mjs +2120 -0
  142. package/scripts/lib/mcp-health.mjs +773 -0
  143. package/scripts/lib/mcp-manifest.mjs +89 -0
  144. package/scripts/lib/mcp-server-catalog.mjs +355 -0
  145. package/scripts/lib/pid.mjs +63 -0
  146. package/scripts/lib/process-utils.mjs +26 -0
  147. package/scripts/lib/psmux-info.mjs +179 -0
  148. package/scripts/lib/quota.mjs +47 -0
  149. package/scripts/lib/remote-spawn-transfer.mjs +226 -0
  150. package/scripts/lib/skill-state.mjs +220 -0
  151. package/scripts/lib/skill-template.mjs +375 -0
  152. package/scripts/lib/team.mjs +75 -0
  153. package/scripts/lib/timeout.mjs +66 -0
  154. package/scripts/lib/tmp.mjs +26 -0
  155. package/scripts/lib/toml.mjs +113 -0
@@ -0,0 +1,288 @@
1
+ // hub/team/tui-core.mjs — 대시보드 공통 유틸리티 (ISSUE-11)
2
+ // tui.mjs / tui-lite.mjs 간 중복 로직을 단일 모듈로 통합.
3
+
4
+ import { FG, MOCHA, wcswidth } from "./ansi.mjs";
5
+
6
+ // ── 상수 ──────────────────────────────────────────────────────────────────
7
+ export const FALLBACK_COLUMNS = 100;
8
+ export const FALLBACK_ROWS = 30;
9
+ export const VALID_TABS = Object.freeze(["log", "detail", "files"]);
10
+
11
+ // ── 버전 로드 ─────────────────────────────────────────────────────────────
12
+ let _cachedVersion = null;
13
+ export async function loadVersion(fallback = "7.x") {
14
+ if (_cachedVersion) return _cachedVersion;
15
+ try {
16
+ const { createRequire } = await import("node:module");
17
+ const require = createRequire(import.meta.url);
18
+ _cachedVersion = require("../../package.json").version;
19
+ } catch {
20
+ _cachedVersion = fallback;
21
+ }
22
+ return _cachedVersion;
23
+ }
24
+
25
+ // ── 수학 유틸 ─────────────────────────────────────────────────────────────
26
+ export function clamp(value, min, max) {
27
+ return Math.min(max, Math.max(min, value));
28
+ }
29
+
30
+ // ── 텍스트 정규화 ─────────────────────────────────────────────────────────
31
+ export function stripCodeBlocks(text) {
32
+ return String(text || "")
33
+ .replace(/\r/g, "")
34
+ .replace(/```[\s\S]*?(?:```|$)/g, "\n")
35
+ .replace(/^\s*```.*$/gm, "")
36
+ .replace(/^(?: {4}|\t).+$/gm, "")
37
+ .replace(/^(?:PS\s+\S[^\n]*?>|>\s+|\$\s+)[^\n]*/gm, "")
38
+ .trim();
39
+ }
40
+
41
+ export function sanitizeTextBlock(text, rawMode = false) {
42
+ const normalized = rawMode
43
+ ? String(text || "").replace(/\r/g, "")
44
+ : stripCodeBlocks(text);
45
+ return normalized
46
+ .split("\n")
47
+ .map((line) => line.trim())
48
+ .filter(Boolean)
49
+ .filter((line) => line !== "--- HANDOFF ---")
50
+ .join("\n")
51
+ .trim();
52
+ }
53
+
54
+ export function sanitizeOneLine(text, fallback = "") {
55
+ return sanitizeTextBlock(text).replace(/\s+/g, " ").trim() || fallback;
56
+ }
57
+
58
+ export function sanitizeFiles(files) {
59
+ if (!files) return [];
60
+ const raw = Array.isArray(files) ? files : String(files).split(",");
61
+ return raw.map((e) => sanitizeOneLine(e)).filter(Boolean);
62
+ }
63
+
64
+ export function sanitizeFindings(findings) {
65
+ if (!findings) return [];
66
+ const raw = Array.isArray(findings)
67
+ ? findings
68
+ : sanitizeTextBlock(findings).split("\n");
69
+ return raw.map((e) => sanitizeOneLine(e)).filter(Boolean);
70
+ }
71
+
72
+ export function normalizeTokens(tokens) {
73
+ if (tokens === null || tokens === undefined || tokens === "") return "";
74
+ if (typeof tokens === "number" && Number.isFinite(tokens)) return tokens;
75
+ const raw = sanitizeOneLine(tokens);
76
+ if (!raw) return "";
77
+ const match = raw.match(/(\d+(?:[.,]\d+)?\s*[kKmM]?)/);
78
+ return match ? match[1].replace(/\s+/g, "").toLowerCase() : raw;
79
+ }
80
+
81
+ export function formatTokens(tokens) {
82
+ if (tokens === null || tokens === undefined || tokens === "") return "n/a";
83
+ if (typeof tokens === "number" && Number.isFinite(tokens)) {
84
+ if (tokens >= 1_000_000) return `${(tokens / 1_000_000).toFixed(1)}m`;
85
+ if (tokens >= 1_000) return `${(tokens / 1_000).toFixed(1)}k`;
86
+ return `${tokens}`;
87
+ }
88
+ return String(tokens);
89
+ }
90
+
91
+ // ── 워커 상태 ─────────────────────────────────────────────────────────────
92
+ export function runtimeStatus(worker) {
93
+ return worker?.handoff?.status || worker?.status || "pending";
94
+ }
95
+
96
+ /**
97
+ * 워커 상태 정규화 (tui.mjs / tui-lite.mjs 공통)
98
+ * @param {object} existing - 기존 워커 상태
99
+ * @param {object} state - 새 상태 패치
100
+ * @param {object} [opts]
101
+ * @param {boolean} [opts.trackChanges=false] - _prevStatus/_statusChangedAt 추적 (full TUI용)
102
+ * @param {function} [opts.now=Date.now] - 시간 함수
103
+ */
104
+ export function normalizeWorkerState(existing = {}, state = {}, opts = {}) {
105
+ const { trackChanges = false, now = Date.now } = opts;
106
+
107
+ const nextHandoff =
108
+ state.handoff === undefined
109
+ ? existing.handoff
110
+ : {
111
+ ...(existing.handoff || {}),
112
+ ...(state.handoff || {}),
113
+ verdict:
114
+ state.handoff?.verdict !== undefined
115
+ ? sanitizeOneLine(state.handoff.verdict)
116
+ : existing.handoff?.verdict,
117
+ confidence:
118
+ state.handoff?.confidence !== undefined
119
+ ? sanitizeOneLine(state.handoff.confidence)
120
+ : existing.handoff?.confidence,
121
+ status:
122
+ state.handoff?.status !== undefined
123
+ ? sanitizeOneLine(state.handoff.status)
124
+ : existing.handoff?.status,
125
+ files_changed:
126
+ state.handoff?.files_changed !== undefined
127
+ ? sanitizeFiles(state.handoff.files_changed)
128
+ : existing.handoff?.files_changed,
129
+ };
130
+
131
+ const merged = {
132
+ ...existing,
133
+ ...state,
134
+ cli:
135
+ state.cli !== undefined
136
+ ? sanitizeOneLine(state.cli, existing.cli || "codex")
137
+ : existing.cli || "codex",
138
+ role:
139
+ state.role !== undefined ? sanitizeOneLine(state.role) : existing.role,
140
+ status:
141
+ state.status !== undefined
142
+ ? sanitizeOneLine(state.status, existing.status || "pending")
143
+ : existing.status || "pending",
144
+ snapshot:
145
+ state.snapshot !== undefined
146
+ ? sanitizeTextBlock(state.snapshot)
147
+ : existing.snapshot,
148
+ summary:
149
+ state.summary !== undefined
150
+ ? sanitizeTextBlock(state.summary)
151
+ : existing.summary,
152
+ detail:
153
+ state.detail !== undefined
154
+ ? sanitizeTextBlock(state.detail)
155
+ : existing.detail,
156
+ findings:
157
+ state.findings !== undefined
158
+ ? sanitizeFindings(state.findings)
159
+ : existing.findings,
160
+ files_changed:
161
+ state.files_changed !== undefined
162
+ ? sanitizeFiles(state.files_changed)
163
+ : existing.files_changed,
164
+ confidence:
165
+ state.confidence !== undefined
166
+ ? sanitizeOneLine(state.confidence)
167
+ : existing.confidence,
168
+ tokens:
169
+ state.tokens !== undefined
170
+ ? normalizeTokens(state.tokens)
171
+ : existing.tokens,
172
+ progress:
173
+ state.progress !== undefined
174
+ ? clamp(Number(state.progress) || 0, 0, 1)
175
+ : existing.progress,
176
+ handoff: nextHandoff,
177
+ };
178
+
179
+ if (trackChanges) {
180
+ const statusChanged =
181
+ state.status !== undefined &&
182
+ sanitizeOneLine(state.status) !== existing.status;
183
+ merged._prevStatus = statusChanged ? existing.status : existing._prevStatus;
184
+ merged._statusChangedAt = statusChanged
185
+ ? now()
186
+ : existing._statusChangedAt || 0;
187
+ }
188
+
189
+ return merged;
190
+ }
191
+
192
+ // ── 색상 헬퍼 ─────────────────────────────────────────────────────────────
193
+ export function cliColor(cli) {
194
+ if (cli === "gemini") return FG.gemini;
195
+ if (cli === "claude") return FG.claude;
196
+ if (cli === "codex") return FG.codex;
197
+ return FG.white;
198
+ }
199
+
200
+ export function statusColor(status) {
201
+ if (status === "ok" || status === "completed") return MOCHA.ok;
202
+ if (status === "partial") return MOCHA.partial;
203
+ if (status === "failed") return MOCHA.fail;
204
+ if (status === "running" || status === "in_progress") return MOCHA.executing;
205
+ return FG.muted;
206
+ }
207
+
208
+ export function countStatuses(names, workers) {
209
+ let ok = 0,
210
+ partial = 0,
211
+ failed = 0,
212
+ running = 0;
213
+ for (const name of names) {
214
+ const st = workers.get(name);
215
+ const s = runtimeStatus(st);
216
+ if (s === "ok" || s === "completed") ok++;
217
+ else if (s === "partial") partial++;
218
+ else if (s === "failed") failed++;
219
+ else if (s === "running" || s === "in_progress") running++;
220
+ }
221
+ return { ok, partial, failed, running };
222
+ }
223
+
224
+ // ── 뷰포트 해상도 ────────────────────────────────────────────────────────
225
+ export function resolveViewportColumns(opts = {}) {
226
+ const { columns, stream } = opts;
227
+ const v = Number.isFinite(columns)
228
+ ? columns
229
+ : Number.isFinite(stream?.columns)
230
+ ? stream.columns
231
+ : Number.isFinite(process.stdout?.columns)
232
+ ? process.stdout.columns
233
+ : FALLBACK_COLUMNS;
234
+ return Math.max(48, v || FALLBACK_COLUMNS);
235
+ }
236
+
237
+ export function resolveViewportRows(opts = {}) {
238
+ const { rows, stream } = opts;
239
+ const v = Number.isFinite(rows)
240
+ ? rows
241
+ : Number.isFinite(stream?.rows)
242
+ ? stream.rows
243
+ : Number.isFinite(process.stdout?.rows)
244
+ ? process.stdout.rows
245
+ : FALLBACK_ROWS;
246
+ return Math.max(10, v || FALLBACK_ROWS);
247
+ }
248
+
249
+ // ── 텍스트 래핑 ───────────────────────────────────────────────────────────
250
+ export function wrapLine(text, width) {
251
+ const limit = Math.max(8, width);
252
+ const source = String(text || "").trim();
253
+ if (!source) return [""];
254
+ const words = source.split(/\s+/);
255
+ const lines = [];
256
+ let current = "";
257
+ for (const word of words) {
258
+ const candidate = current ? `${current} ${word}` : word;
259
+ if (wcswidth(candidate) <= limit) {
260
+ current = candidate;
261
+ continue;
262
+ }
263
+ if (current) {
264
+ lines.push(current);
265
+ current = "";
266
+ }
267
+ if (wcswidth(word) <= limit) {
268
+ current = word;
269
+ continue;
270
+ }
271
+ let offset = 0;
272
+ while (offset < word.length) {
273
+ lines.push(word.slice(offset, offset + limit));
274
+ offset += limit;
275
+ }
276
+ }
277
+ if (current) lines.push(current);
278
+ return lines.length > 0 ? lines : [source.slice(0, limit)];
279
+ }
280
+
281
+ export function wrapText(text, width, rawMode = false) {
282
+ const input = sanitizeTextBlock(text, rawMode);
283
+ if (!input) return [];
284
+ return input
285
+ .split("\n")
286
+ .flatMap((line) => wrapLine(line, width))
287
+ .filter(Boolean);
288
+ }