@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
package/hub/team/agent-map.json
CHANGED
|
@@ -1,11 +1,30 @@
|
|
|
1
1
|
{
|
|
2
|
-
"executor": "codex",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
2
|
+
"executor": "codex",
|
|
3
|
+
"build-fixer": "codex",
|
|
4
|
+
"cleanup": "codex",
|
|
5
|
+
"deslop": "codex",
|
|
6
|
+
"debugger": "codex",
|
|
7
|
+
"deep-executor": "codex",
|
|
8
|
+
"architect": "codex",
|
|
9
|
+
"planner": "codex",
|
|
10
|
+
"critic": "codex",
|
|
11
|
+
"analyst": "codex",
|
|
12
|
+
"code-reviewer": "codex",
|
|
13
|
+
"security-reviewer": "codex",
|
|
14
|
+
"quality-reviewer": "codex",
|
|
15
|
+
"scientist": "codex",
|
|
16
|
+
"scientist-deep": "codex",
|
|
17
|
+
"document-specialist": "codex",
|
|
6
18
|
"spark": "codex",
|
|
7
|
-
"designer": "gemini",
|
|
19
|
+
"designer": "gemini",
|
|
20
|
+
"writer": "gemini",
|
|
8
21
|
"explore": "claude",
|
|
9
|
-
"verifier": "codex",
|
|
10
|
-
"
|
|
22
|
+
"verifier": "codex",
|
|
23
|
+
"test-engineer": "codex",
|
|
24
|
+
"qa-tester": "codex",
|
|
25
|
+
"codex": "codex",
|
|
26
|
+
"gemini": "gemini",
|
|
27
|
+
"antigravity": "antigravity",
|
|
28
|
+
"agy": "antigravity",
|
|
29
|
+
"claude": "claude"
|
|
11
30
|
}
|
package/hub/team/ansi.mjs
CHANGED
|
@@ -7,54 +7,60 @@
|
|
|
7
7
|
export const ESC = "\x1b";
|
|
8
8
|
|
|
9
9
|
// ── 화면 ──
|
|
10
|
-
export const altScreenOn
|
|
10
|
+
export const altScreenOn = `${ESC}[?1049h`;
|
|
11
11
|
export const altScreenOff = `${ESC}[?1049l`;
|
|
12
|
-
export const clearScreen
|
|
13
|
-
export const cursorHome
|
|
14
|
-
export const cursorHide
|
|
15
|
-
export const cursorShow
|
|
12
|
+
export const clearScreen = `${ESC}[2J`;
|
|
13
|
+
export const cursorHome = `${ESC}[H`;
|
|
14
|
+
export const cursorHide = `${ESC}[?25l`;
|
|
15
|
+
export const cursorShow = `${ESC}[?25h`;
|
|
16
16
|
|
|
17
17
|
// ── 커서 이동 ──
|
|
18
|
-
export function moveTo(row, col) {
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
export function moveTo(row, col) {
|
|
19
|
+
return `${ESC}[${row};${col}H`;
|
|
20
|
+
}
|
|
21
|
+
export function moveUp(n = 1) {
|
|
22
|
+
return `${ESC}[${n}A`;
|
|
23
|
+
}
|
|
24
|
+
export function moveDown(n = 1) {
|
|
25
|
+
return `${ESC}[${n}B`;
|
|
26
|
+
}
|
|
21
27
|
|
|
22
28
|
// ── 줄 제어 ──
|
|
23
|
-
export const clearLine
|
|
24
|
-
export const clearToEnd
|
|
25
|
-
export const eraseBelow
|
|
29
|
+
export const clearLine = `${ESC}[2K`;
|
|
30
|
+
export const clearToEnd = `${ESC}[K`;
|
|
31
|
+
export const eraseBelow = `${ESC}[J`;
|
|
26
32
|
|
|
27
33
|
// ── 색상 (triflux 디자인 시스템) ──
|
|
28
34
|
export const RESET = `${ESC}[0m`;
|
|
29
|
-
export const BOLD
|
|
30
|
-
export const DIM
|
|
35
|
+
export const BOLD = `${ESC}[1m`;
|
|
36
|
+
export const DIM = `${ESC}[2m`;
|
|
31
37
|
|
|
32
38
|
export const FG = {
|
|
33
|
-
white:
|
|
34
|
-
black:
|
|
35
|
-
red:
|
|
36
|
-
green:
|
|
37
|
-
yellow:
|
|
38
|
-
blue:
|
|
39
|
-
magenta:
|
|
40
|
-
cyan:
|
|
41
|
-
gray:
|
|
39
|
+
white: `${ESC}[97m`,
|
|
40
|
+
black: `${ESC}[30m`,
|
|
41
|
+
red: `${ESC}[31m`,
|
|
42
|
+
green: `${ESC}[32m`,
|
|
43
|
+
yellow: `${ESC}[33m`,
|
|
44
|
+
blue: `${ESC}[34m`,
|
|
45
|
+
magenta: `${ESC}[35m`,
|
|
46
|
+
cyan: `${ESC}[36m`,
|
|
47
|
+
gray: `${ESC}[90m`,
|
|
42
48
|
// triflux 브랜드
|
|
43
|
-
codex:
|
|
44
|
-
gemini:
|
|
45
|
-
claude:
|
|
46
|
-
triflux:
|
|
47
|
-
accent:
|
|
48
|
-
muted:
|
|
49
|
+
codex: `${ESC}[38;2;16;163;127m`, // #10a37f codex green
|
|
50
|
+
gemini: `${ESC}[38;5;39m`, // blue
|
|
51
|
+
claude: `${ESC}[38;2;232;112;64m`, // orange
|
|
52
|
+
triflux: `${ESC}[38;5;214m`, // amber
|
|
53
|
+
accent: `${ESC}[38;5;75m`, // light blue (Catppuccin blue)
|
|
54
|
+
muted: `${ESC}[38;5;245m`, // gray
|
|
49
55
|
};
|
|
50
56
|
|
|
51
57
|
export const BG = {
|
|
52
|
-
black:
|
|
53
|
-
red:
|
|
54
|
-
green:
|
|
55
|
-
yellow:
|
|
56
|
-
blue:
|
|
57
|
-
header:
|
|
58
|
+
black: `${ESC}[40m`,
|
|
59
|
+
red: `${ESC}[41m`,
|
|
60
|
+
green: `${ESC}[42m`,
|
|
61
|
+
yellow: `${ESC}[43m`,
|
|
62
|
+
blue: `${ESC}[44m`,
|
|
63
|
+
header: `${ESC}[48;5;236m`, // dark gray
|
|
58
64
|
};
|
|
59
65
|
|
|
60
66
|
// ── 색상 헬퍼 ──
|
|
@@ -63,8 +69,12 @@ export function color(text, fg, bg) {
|
|
|
63
69
|
return prefix ? `${prefix}${text}${RESET}` : text;
|
|
64
70
|
}
|
|
65
71
|
|
|
66
|
-
export function bold(text)
|
|
67
|
-
|
|
72
|
+
export function bold(text) {
|
|
73
|
+
return `${BOLD}${text}${RESET}`;
|
|
74
|
+
}
|
|
75
|
+
export function dim(text) {
|
|
76
|
+
return `${DIM}${text}${RESET}`;
|
|
77
|
+
}
|
|
68
78
|
|
|
69
79
|
export function lerpRgb(a, b, t) {
|
|
70
80
|
return {
|
|
@@ -83,9 +93,10 @@ function brightenRgb(rgb, amount = 0.3) {
|
|
|
83
93
|
}
|
|
84
94
|
|
|
85
95
|
function parseRgbSeq(seq) {
|
|
86
|
-
const match =
|
|
87
|
-
|
|
88
|
-
|
|
96
|
+
const match =
|
|
97
|
+
typeof seq === "string"
|
|
98
|
+
? seq.match(/\x1b\[(?:38|48);2;(\d+);(\d+);(\d+)m/)
|
|
99
|
+
: null;
|
|
89
100
|
if (!match) return null;
|
|
90
101
|
return {
|
|
91
102
|
r: Number.parseInt(match[1], 10),
|
|
@@ -100,7 +111,16 @@ function reapplyBackground(text, bgSeq) {
|
|
|
100
111
|
}
|
|
101
112
|
|
|
102
113
|
// ── 박스 그리기 (유니코드 테두리) ──
|
|
103
|
-
const BOX = {
|
|
114
|
+
const BOX = {
|
|
115
|
+
tl: "┌",
|
|
116
|
+
tr: "┐",
|
|
117
|
+
bl: "└",
|
|
118
|
+
br: "┘",
|
|
119
|
+
h: "─",
|
|
120
|
+
v: "│",
|
|
121
|
+
ml: "├",
|
|
122
|
+
mr: "┤",
|
|
123
|
+
};
|
|
104
124
|
|
|
105
125
|
function borderHighlightCell(width, totalRows, highlightPos) {
|
|
106
126
|
if (!Number.isFinite(highlightPos)) return null;
|
|
@@ -118,7 +138,14 @@ function borderHighlightCell(width, totalRows, highlightPos) {
|
|
|
118
138
|
return { row: totalRows - 1 - pos, col: 0 };
|
|
119
139
|
}
|
|
120
140
|
|
|
121
|
-
function renderBorderChar(
|
|
141
|
+
function renderBorderChar(
|
|
142
|
+
glyph,
|
|
143
|
+
row,
|
|
144
|
+
col,
|
|
145
|
+
highlightCell,
|
|
146
|
+
borderSeq,
|
|
147
|
+
highlightSeq,
|
|
148
|
+
) {
|
|
122
149
|
if (highlightCell && highlightCell.row === row && highlightCell.col === col) {
|
|
123
150
|
return `${highlightSeq}${glyph}${RESET}`;
|
|
124
151
|
}
|
|
@@ -128,28 +155,75 @@ function renderBorderChar(glyph, row, col, highlightCell, borderSeq, highlightSe
|
|
|
128
155
|
export function box(lines, width, borderColor = "", options = {}) {
|
|
129
156
|
const isFn = typeof borderColor === "function";
|
|
130
157
|
const totalRows = lines.length + 2;
|
|
158
|
+
const highlightCell = borderHighlightCell(
|
|
159
|
+
width,
|
|
160
|
+
totalRows,
|
|
161
|
+
options.highlightPos,
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
// Fast path: static border, no highlight — batch border chars (~13x less output)
|
|
165
|
+
if (!highlightCell && !isFn) {
|
|
166
|
+
const bc = borderColor || "";
|
|
167
|
+
const rst = bc ? RESET : "";
|
|
168
|
+
const hLine = BOX.h.repeat(Math.max(0, width - 2));
|
|
169
|
+
const top = `${bc}${BOX.tl}${hLine}${BOX.tr}${rst}`;
|
|
170
|
+
const bot = `${bc}${BOX.bl}${hLine}${BOX.br}${rst}`;
|
|
171
|
+
const mid = `${bc}${BOX.ml}${hLine}${BOX.mr}${rst}`;
|
|
172
|
+
const body = lines.map((l, i) => {
|
|
173
|
+
const content =
|
|
174
|
+
options.titleFlashBg && i === 0
|
|
175
|
+
? reapplyBackground(padRight(l, width - 4), options.titleFlashBg)
|
|
176
|
+
: padRight(l, width - 4);
|
|
177
|
+
return `${bc}${BOX.v}${rst} ${content} ${bc}${BOX.v}${rst}`;
|
|
178
|
+
});
|
|
179
|
+
return { top, body, bot, mid };
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Slow path: per-character rendering for highlight animation
|
|
131
183
|
const bc = isFn ? (row) => borderColor(row, totalRows) : () => borderColor;
|
|
132
|
-
const rst =
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
const parsed = parseRgbSeq(
|
|
184
|
+
const rst = isFn || borderColor ? RESET : "";
|
|
185
|
+
const highlightSeq =
|
|
186
|
+
options.highlightColor ||
|
|
187
|
+
(() => {
|
|
188
|
+
const parsed = parseRgbSeq(
|
|
189
|
+
typeof borderColor === "string" ? borderColor : "",
|
|
190
|
+
);
|
|
137
191
|
return parsed ? rgbSeq(brightenRgb(parsed, 0.45)) : `${BOLD}${FG.white}`;
|
|
138
192
|
})();
|
|
139
|
-
const topChars = [
|
|
140
|
-
|
|
193
|
+
const topChars = [
|
|
194
|
+
BOX.tl,
|
|
195
|
+
...Array.from({ length: width - 2 }, () => BOX.h),
|
|
196
|
+
BOX.tr,
|
|
197
|
+
];
|
|
198
|
+
const botChars = [
|
|
199
|
+
BOX.bl,
|
|
200
|
+
...Array.from({ length: width - 2 }, () => BOX.h),
|
|
201
|
+
BOX.br,
|
|
202
|
+
];
|
|
141
203
|
const top = topChars
|
|
142
|
-
.map((glyph, col) =>
|
|
204
|
+
.map((glyph, col) =>
|
|
205
|
+
renderBorderChar(glyph, 0, col, highlightCell, bc(0), highlightSeq),
|
|
206
|
+
)
|
|
143
207
|
.join("");
|
|
144
208
|
const bot = botChars
|
|
145
|
-
.map((glyph, col) =>
|
|
209
|
+
.map((glyph, col) =>
|
|
210
|
+
renderBorderChar(
|
|
211
|
+
glyph,
|
|
212
|
+
totalRows - 1,
|
|
213
|
+
col,
|
|
214
|
+
highlightCell,
|
|
215
|
+
bc(totalRows - 1),
|
|
216
|
+
highlightSeq,
|
|
217
|
+
),
|
|
218
|
+
)
|
|
146
219
|
.join("");
|
|
147
|
-
const mid = `${bc(Math.floor(totalRows / 2))}${BOX.ml}${BOX.h.repeat(width - 2)}${BOX.mr}${rst}`;
|
|
220
|
+
const mid = `${bc(Math.floor(totalRows / 2))}${BOX.ml}${BOX.h.repeat(Math.max(0, width - 2))}${BOX.mr}${rst}`;
|
|
148
221
|
const body = lines.map((l, i) => {
|
|
149
222
|
const row = i + 1;
|
|
150
|
-
const content =
|
|
151
|
-
|
|
152
|
-
|
|
223
|
+
const content =
|
|
224
|
+
options.titleFlashBg && i === 0
|
|
225
|
+
? reapplyBackground(padRight(l, width - 4), options.titleFlashBg)
|
|
226
|
+
: padRight(l, width - 4);
|
|
153
227
|
return `${renderBorderChar(BOX.v, row, 0, highlightCell, bc(row), highlightSeq)} ${content} ${renderBorderChar(BOX.v, row, width - 1, highlightCell, bc(row), highlightSeq)}`;
|
|
154
228
|
});
|
|
155
229
|
return { top, body, bot, mid };
|
|
@@ -160,50 +234,53 @@ export function box(lines, width, borderColor = "", options = {}) {
|
|
|
160
234
|
function charWidth(cp) {
|
|
161
235
|
// combining / zero-width 범위
|
|
162
236
|
if (
|
|
163
|
-
cp === 0 ||
|
|
164
|
-
|
|
165
|
-
(cp >=
|
|
166
|
-
(cp >=
|
|
167
|
-
(cp >=
|
|
168
|
-
(cp >=
|
|
169
|
-
(cp >=
|
|
170
|
-
(cp >=
|
|
171
|
-
|
|
237
|
+
cp === 0 ||
|
|
238
|
+
cp === 0xad ||
|
|
239
|
+
(cp >= 0x0300 && cp <= 0x036f) || // Combining Diacritical Marks
|
|
240
|
+
(cp >= 0x0610 && cp <= 0x061a) ||
|
|
241
|
+
(cp >= 0x064b && cp <= 0x065f) ||
|
|
242
|
+
(cp >= 0x1ab0 && cp <= 0x1aff) ||
|
|
243
|
+
(cp >= 0x1dc0 && cp <= 0x1dff) ||
|
|
244
|
+
(cp >= 0x20d0 && cp <= 0x20ff) || // Combining Diacritical Marks for Symbols
|
|
245
|
+
(cp >= 0xfe20 && cp <= 0xfe2f) // Combining Half Marks
|
|
246
|
+
)
|
|
247
|
+
return 0;
|
|
172
248
|
|
|
173
249
|
// Wide: CJK Unified Ideographs, Hangul, Fullwidth, emoji 주요 블록
|
|
174
250
|
if (
|
|
175
|
-
(cp >= 0x1100 && cp <=
|
|
176
|
-
(cp >=
|
|
177
|
-
(cp >=
|
|
178
|
-
(cp >= 0x3000 && cp <=
|
|
179
|
-
(cp >= 0x3040 && cp <=
|
|
180
|
-
(cp >=
|
|
181
|
-
(cp >= 0x3100 && cp <=
|
|
182
|
-
(cp >= 0x3130 && cp <=
|
|
183
|
-
(cp >= 0x3190 && cp <=
|
|
184
|
-
(cp >=
|
|
185
|
-
(cp >= 0x3200 && cp <=
|
|
186
|
-
(cp >= 0x3300 && cp <=
|
|
187
|
-
(cp >= 0x3400 && cp <=
|
|
188
|
-
(cp >=
|
|
189
|
-
(cp >=
|
|
190
|
-
(cp >=
|
|
191
|
-
(cp >=
|
|
192
|
-
(cp >=
|
|
193
|
-
(cp >=
|
|
194
|
-
(cp >=
|
|
195
|
-
(cp >=
|
|
196
|
-
(cp >=
|
|
197
|
-
(cp >=
|
|
198
|
-
(cp >=
|
|
199
|
-
(cp >=
|
|
200
|
-
(cp >=
|
|
201
|
-
(cp >=
|
|
202
|
-
(cp >=
|
|
203
|
-
(cp >=
|
|
204
|
-
(cp >= 0x20000 && cp <=
|
|
205
|
-
(cp >= 0x30000 && cp <=
|
|
206
|
-
)
|
|
251
|
+
(cp >= 0x1100 && cp <= 0x115f) || // Hangul Jamo
|
|
252
|
+
(cp >= 0x2e80 && cp <= 0x2eff) || // CJK Radicals Supplement
|
|
253
|
+
(cp >= 0x2f00 && cp <= 0x2fff) ||
|
|
254
|
+
(cp >= 0x3000 && cp <= 0x303f) || // CJK Symbols and Punctuation
|
|
255
|
+
(cp >= 0x3040 && cp <= 0x309f) || // Hiragana
|
|
256
|
+
(cp >= 0x30a0 && cp <= 0x30ff) || // Katakana
|
|
257
|
+
(cp >= 0x3100 && cp <= 0x312f) ||
|
|
258
|
+
(cp >= 0x3130 && cp <= 0x318f) || // Hangul Compatibility Jamo
|
|
259
|
+
(cp >= 0x3190 && cp <= 0x319f) ||
|
|
260
|
+
(cp >= 0x31c0 && cp <= 0x31ef) ||
|
|
261
|
+
(cp >= 0x3200 && cp <= 0x32ff) ||
|
|
262
|
+
(cp >= 0x3300 && cp <= 0x33ff) ||
|
|
263
|
+
(cp >= 0x3400 && cp <= 0x4dbf) ||
|
|
264
|
+
(cp >= 0x4e00 && cp <= 0x9fff) || // CJK Unified Ideographs
|
|
265
|
+
(cp >= 0xa000 && cp <= 0xa48f) ||
|
|
266
|
+
(cp >= 0xa490 && cp <= 0xa4cf) ||
|
|
267
|
+
(cp >= 0xa960 && cp <= 0xa97f) ||
|
|
268
|
+
(cp >= 0xac00 && cp <= 0xd7af) || // Hangul Syllables
|
|
269
|
+
(cp >= 0xf900 && cp <= 0xfaff) || // CJK Compatibility Ideographs
|
|
270
|
+
(cp >= 0xfe10 && cp <= 0xfe1f) ||
|
|
271
|
+
(cp >= 0xfe30 && cp <= 0xfe4f) ||
|
|
272
|
+
(cp >= 0xff00 && cp <= 0xff60) || // Fullwidth Forms
|
|
273
|
+
(cp >= 0xffe0 && cp <= 0xffe6) ||
|
|
274
|
+
(cp >= 0x1b000 && cp <= 0x1b0ff) ||
|
|
275
|
+
(cp >= 0x1f004 && cp <= 0x1f0cf) ||
|
|
276
|
+
(cp >= 0x1f200 && cp <= 0x1f2ff) ||
|
|
277
|
+
(cp >= 0x1f300 && cp <= 0x1f64f) || // Misc Symbols, Emoticons
|
|
278
|
+
(cp >= 0x1f680 && cp <= 0x1f6ff) || // Transport & Map
|
|
279
|
+
(cp >= 0x1f900 && cp <= 0x1faff) || // Supplemental Symbols
|
|
280
|
+
(cp >= 0x20000 && cp <= 0x2fffd) ||
|
|
281
|
+
(cp >= 0x30000 && cp <= 0x3fffd)
|
|
282
|
+
)
|
|
283
|
+
return 2;
|
|
207
284
|
|
|
208
285
|
return 1;
|
|
209
286
|
}
|
|
@@ -230,62 +307,78 @@ export function padRight(str, len) {
|
|
|
230
307
|
return str + " ".repeat(pad);
|
|
231
308
|
}
|
|
232
309
|
|
|
233
|
-
//
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
let acc = 0;
|
|
310
|
+
// ANSI-preserving slice: ANSI escape를 보존하면서 visible width만큼 자름
|
|
311
|
+
function ansiSlice(str, maxWidth) {
|
|
312
|
+
let result = "";
|
|
313
|
+
let visWidth = 0;
|
|
314
|
+
let hasAnsi = false;
|
|
240
315
|
let i = 0;
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
if (
|
|
244
|
-
|
|
245
|
-
|
|
316
|
+
|
|
317
|
+
while (i < str.length) {
|
|
318
|
+
if (str.charCodeAt(i) === 0x1b) {
|
|
319
|
+
const rest = str.slice(i);
|
|
320
|
+
const m = rest.match(/^(\x1b(?:\[[0-9;]*[a-zA-Z]|\].*?(?:\x07|\x1b\\)))/);
|
|
321
|
+
if (m) {
|
|
322
|
+
result += m[1];
|
|
323
|
+
hasAnsi = true;
|
|
324
|
+
i += m[1].length;
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
const cp = str.codePointAt(i);
|
|
330
|
+
const charLen = cp > 0xffff ? 2 : 1;
|
|
331
|
+
const cw = charWidth(cp);
|
|
332
|
+
|
|
333
|
+
if (visWidth + cw > maxWidth) break;
|
|
334
|
+
|
|
335
|
+
result += str.slice(i, i + charLen);
|
|
336
|
+
visWidth += cw;
|
|
337
|
+
i += charLen;
|
|
246
338
|
}
|
|
247
|
-
|
|
339
|
+
|
|
340
|
+
return { result, visWidth, hasAnsi };
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// wcwidth-aware truncate: wide char 경계에서 자름 (ANSI 보존)
|
|
344
|
+
export function truncate(str, maxLen) {
|
|
345
|
+
if (wcswidth(str) <= maxLen) return str;
|
|
346
|
+
|
|
347
|
+
const { result, hasAnsi } = ansiSlice(str, maxLen - 1);
|
|
348
|
+
return hasAnsi ? result + RESET + "…" : result + "…";
|
|
248
349
|
}
|
|
249
350
|
|
|
250
|
-
// wcwidth-aware clip: 정확히 width 셀에 맞게 자르고 패딩 (wide char 경계 보정)
|
|
351
|
+
// wcwidth-aware clip: 정확히 width 셀에 맞게 자르고 패딩 (ANSI 보존, wide char 경계 보정)
|
|
251
352
|
export function clip(str, width) {
|
|
252
|
-
const
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
// wide char이 경계를 넘으면 공백으로 채움
|
|
259
|
-
const result = plain.slice(0, i) + " ".repeat(width - acc);
|
|
260
|
-
return result;
|
|
261
|
-
}
|
|
262
|
-
acc += cw;
|
|
263
|
-
i += char.length;
|
|
264
|
-
}
|
|
265
|
-
return str + " ".repeat(width - acc);
|
|
353
|
+
const vis = wcswidth(str);
|
|
354
|
+
if (vis <= width) return str + " ".repeat(width - vis);
|
|
355
|
+
|
|
356
|
+
const { result, visWidth, hasAnsi } = ansiSlice(str, width);
|
|
357
|
+
const suffix = hasAnsi ? RESET : "";
|
|
358
|
+
return result + suffix + " ".repeat(Math.max(0, width - visWidth));
|
|
266
359
|
}
|
|
267
360
|
|
|
268
361
|
// ── Catppuccin Mocha 색상 상수 ──
|
|
269
362
|
export const MOCHA = {
|
|
270
|
-
ok:
|
|
271
|
-
partial:
|
|
272
|
-
fail:
|
|
273
|
-
thinking:
|
|
274
|
-
executing: `${ESC}[38;5;117m`,
|
|
275
|
-
border:
|
|
276
|
-
text:
|
|
277
|
-
subtext:
|
|
278
|
-
overlay:
|
|
279
|
-
blue:
|
|
280
|
-
yellow:
|
|
281
|
-
red:
|
|
282
|
-
surface0:
|
|
363
|
+
ok: `${ESC}[38;5;114m`, // #a6e3a1 green
|
|
364
|
+
partial: `${ESC}[38;5;216m`, // #fab387 peach
|
|
365
|
+
fail: `${ESC}[38;5;210m`, // #f38ba8 red
|
|
366
|
+
thinking: `${ESC}[38;5;183m`, // #cba6f7 mauve
|
|
367
|
+
executing: `${ESC}[38;5;117m`, // #74c7ec sky
|
|
368
|
+
border: `${ESC}[38;5;238m`, // #45475a surface1
|
|
369
|
+
text: `${ESC}[38;2;205;214;244m`, // #cdd6f4 catppuccin text
|
|
370
|
+
subtext: `${ESC}[38;2;166;173;200m`, // #a6adc8 subtext0
|
|
371
|
+
overlay: `${ESC}[38;2;108;112;134m`, // #6c7086 overlay0
|
|
372
|
+
blue: `${ESC}[38;2;137;180;250m`, // #89b4fa blue
|
|
373
|
+
yellow: `${ESC}[38;2;249;226;175m`, // #f9e2af yellow
|
|
374
|
+
red: `${ESC}[38;2;243;139;168m`, // #f38ba8 red (truecolor)
|
|
375
|
+
surface0: `${ESC}[38;2;49;50;68m`, // #313244 surface0
|
|
283
376
|
};
|
|
284
377
|
|
|
285
378
|
const MOCHA_RGB = {
|
|
286
|
-
ok:
|
|
287
|
-
partial:
|
|
288
|
-
fail:
|
|
379
|
+
ok: { r: 166, g: 227, b: 161 },
|
|
380
|
+
partial: { r: 250, g: 179, b: 135 },
|
|
381
|
+
fail: { r: 243, g: 139, b: 168 },
|
|
289
382
|
};
|
|
290
383
|
|
|
291
384
|
// ── badge 헬퍼 ──
|
|
@@ -319,7 +412,12 @@ export function progressBar(percent, width = 20, time) {
|
|
|
319
412
|
const ratio = Math.max(0, Math.min(100, percent)) / 100;
|
|
320
413
|
const filled = Math.round(ratio * width);
|
|
321
414
|
const empty = width - filled;
|
|
322
|
-
const fillRgb =
|
|
415
|
+
const fillRgb =
|
|
416
|
+
percent >= 100
|
|
417
|
+
? MOCHA_RGB.ok
|
|
418
|
+
: percent >= 50
|
|
419
|
+
? MOCHA_RGB.partial
|
|
420
|
+
: MOCHA_RGB.fail;
|
|
323
421
|
const fillColor = rgbSeq(fillRgb);
|
|
324
422
|
let fillText = "█".repeat(filled);
|
|
325
423
|
|
|
@@ -330,13 +428,14 @@ export function progressBar(percent, width = 20, time) {
|
|
|
330
428
|
);
|
|
331
429
|
const shineColor = rgbSeq(brightenRgb(fillRgb, 0.3));
|
|
332
430
|
fillText = Array.from({ length: filled }, (_, idx) =>
|
|
333
|
-
idx === shinePos ? `${shineColor}█${RESET}` : `${fillColor}█${RESET}
|
|
431
|
+
idx === shinePos ? `${shineColor}█${RESET}` : `${fillColor}█${RESET}`,
|
|
334
432
|
).join("");
|
|
335
433
|
} else if (filled > 0) {
|
|
336
434
|
fillText = `${fillColor}${fillText}${RESET}`;
|
|
337
435
|
}
|
|
338
436
|
|
|
339
|
-
const emptyText =
|
|
437
|
+
const emptyText =
|
|
438
|
+
empty > 0 ? `${MOCHA.border}${"░".repeat(empty)}${RESET}` : "";
|
|
340
439
|
return `${fillText}${emptyText}`;
|
|
341
440
|
}
|
|
342
441
|
|
|
@@ -360,14 +459,14 @@ export function animatedProgressBar(percent, width = 20, tick = 0) {
|
|
|
360
459
|
|
|
361
460
|
// ── 상태 아이콘 ──
|
|
362
461
|
export const STATUS_ICON = {
|
|
363
|
-
running:
|
|
462
|
+
running: `${MOCHA.partial}⏳${RESET}`,
|
|
364
463
|
completed: `${MOCHA.ok}✓${RESET}`,
|
|
365
|
-
failed:
|
|
366
|
-
pending:
|
|
464
|
+
failed: `${MOCHA.fail}✗${RESET}`,
|
|
465
|
+
pending: `${FG.gray}⏸${RESET}`,
|
|
367
466
|
};
|
|
368
467
|
|
|
369
468
|
export const CLI_ICON = {
|
|
370
|
-
codex:
|
|
469
|
+
codex: `${FG.codex}⚪${RESET}`,
|
|
371
470
|
gemini: `${FG.gemini}🔵${RESET}`,
|
|
372
471
|
claude: `${FG.claude}🟠${RESET}`,
|
|
373
472
|
};
|