@triflux/remote 10.0.0-alpha.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 (68) hide show
  1. package/hub/pipe.mjs +579 -0
  2. package/hub/public/dashboard.html +355 -0
  3. package/hub/public/tray-icon.ico +0 -0
  4. package/hub/public/tray-icon.png +0 -0
  5. package/hub/server.mjs +1124 -0
  6. package/hub/store-adapter.mjs +851 -0
  7. package/hub/store.mjs +897 -0
  8. package/hub/team/agent-map.json +11 -0
  9. package/hub/team/ansi.mjs +379 -0
  10. package/hub/team/backend.mjs +90 -0
  11. package/hub/team/cli/commands/attach.mjs +37 -0
  12. package/hub/team/cli/commands/control.mjs +43 -0
  13. package/hub/team/cli/commands/debug.mjs +74 -0
  14. package/hub/team/cli/commands/focus.mjs +53 -0
  15. package/hub/team/cli/commands/interrupt.mjs +36 -0
  16. package/hub/team/cli/commands/kill.mjs +37 -0
  17. package/hub/team/cli/commands/list.mjs +24 -0
  18. package/hub/team/cli/commands/send.mjs +37 -0
  19. package/hub/team/cli/commands/start/index.mjs +106 -0
  20. package/hub/team/cli/commands/start/parse-args.mjs +130 -0
  21. package/hub/team/cli/commands/start/start-headless.mjs +109 -0
  22. package/hub/team/cli/commands/start/start-in-process.mjs +40 -0
  23. package/hub/team/cli/commands/start/start-mux.mjs +73 -0
  24. package/hub/team/cli/commands/start/start-wt.mjs +69 -0
  25. package/hub/team/cli/commands/status.mjs +87 -0
  26. package/hub/team/cli/commands/stop.mjs +31 -0
  27. package/hub/team/cli/commands/task.mjs +30 -0
  28. package/hub/team/cli/commands/tasks.mjs +13 -0
  29. package/hub/team/cli/help.mjs +42 -0
  30. package/hub/team/cli/index.mjs +41 -0
  31. package/hub/team/cli/manifest.mjs +29 -0
  32. package/hub/team/cli/render.mjs +30 -0
  33. package/hub/team/cli/services/attach-fallback.mjs +54 -0
  34. package/hub/team/cli/services/hub-client.mjs +208 -0
  35. package/hub/team/cli/services/member-selector.mjs +30 -0
  36. package/hub/team/cli/services/native-control.mjs +117 -0
  37. package/hub/team/cli/services/runtime-mode.mjs +62 -0
  38. package/hub/team/cli/services/state-store.mjs +48 -0
  39. package/hub/team/cli/services/task-model.mjs +30 -0
  40. package/hub/team/dashboard-anchor.mjs +14 -0
  41. package/hub/team/dashboard-layout.mjs +33 -0
  42. package/hub/team/dashboard-open.mjs +153 -0
  43. package/hub/team/dashboard.mjs +274 -0
  44. package/hub/team/handoff.mjs +303 -0
  45. package/hub/team/headless.mjs +1149 -0
  46. package/hub/team/native-supervisor.mjs +392 -0
  47. package/hub/team/native.mjs +649 -0
  48. package/hub/team/nativeProxy.mjs +681 -0
  49. package/hub/team/orchestrator.mjs +161 -0
  50. package/hub/team/pane.mjs +153 -0
  51. package/hub/team/psmux.mjs +1354 -0
  52. package/hub/team/routing.mjs +223 -0
  53. package/hub/team/session.mjs +611 -0
  54. package/hub/team/shared.mjs +13 -0
  55. package/hub/team/staleState.mjs +361 -0
  56. package/hub/team/tui-lite.mjs +380 -0
  57. package/hub/team/tui-viewer.mjs +463 -0
  58. package/hub/team/tui.mjs +1245 -0
  59. package/hub/tools.mjs +554 -0
  60. package/hub/tray.mjs +376 -0
  61. package/hub/workers/claude-worker.mjs +475 -0
  62. package/hub/workers/codex-mcp.mjs +504 -0
  63. package/hub/workers/delegator-mcp.mjs +1076 -0
  64. package/hub/workers/factory.mjs +21 -0
  65. package/hub/workers/gemini-worker.mjs +373 -0
  66. package/hub/workers/interface.mjs +52 -0
  67. package/hub/workers/worker-utils.mjs +104 -0
  68. package/package.json +31 -0
@@ -0,0 +1,223 @@
1
+ /**
2
+ * 라우팅 결정 함수
3
+ * @param {object} opts
4
+ * @param {Array<{id:string, description?:string, agent?:string, depends_on?:string[], complexity?:string}>} opts.subtasks
5
+ * @param {string} opts.graph_type - "INDEPENDENT" | "SEQUENTIAL" | "DAG"
6
+ * @param {boolean} opts.thorough - thorough 모드 여부
7
+ * @returns {{
8
+ * strategy: "quick_single" | "thorough_single" | "quick_team" | "thorough_team" | "batch_single",
9
+ * reason: string,
10
+ * dag_width: number,
11
+ * max_complexity: string,
12
+ * dagContext: { dag_width: number, levels: Record<number, string[]>, edges: Array<{from:string, to:string}>, max_complexity: string, taskResults: Record<string, *> }
13
+ * }}
14
+ */
15
+ export function resolveRoutingStrategy({ subtasks, graph_type, thorough }) {
16
+ const N = subtasks.length;
17
+ if (N === 0) {
18
+ const dagContext = { dag_width: 0, levels: {}, edges: [], max_complexity: 'S', taskResults: {} };
19
+ return { strategy: 'quick_single', reason: 'empty_subtasks', dag_width: 0, max_complexity: 'S', dagContext };
20
+ }
21
+
22
+ const { width: dag_width, levels, edges } = computeDagInfo(subtasks, graph_type);
23
+ const max_complexity = getMaxComplexity(subtasks);
24
+ const dagContext = { dag_width, levels, edges, max_complexity, taskResults: {} };
25
+ const isHighComplexity = ['L', 'XL'].includes(max_complexity);
26
+ const allSameAgent = new Set(subtasks.map((s) => s.agent)).size === 1;
27
+ const allSmall = subtasks.every((s) => normalizeComplexity(s.complexity) === 'S');
28
+
29
+ // N==1: 단일 태스크
30
+ if (N === 1) {
31
+ if (thorough || isHighComplexity) {
32
+ return {
33
+ strategy: 'thorough_single',
34
+ reason: 'single_high_complexity',
35
+ dag_width,
36
+ max_complexity,
37
+ dagContext,
38
+ };
39
+ }
40
+ return {
41
+ strategy: 'quick_single',
42
+ reason: 'single_low_complexity',
43
+ dag_width,
44
+ max_complexity,
45
+ dagContext,
46
+ };
47
+ }
48
+
49
+ // dag_width==1: 사실상 순차 -> single
50
+ if (dag_width === 1) {
51
+ if (thorough || isHighComplexity) {
52
+ return {
53
+ strategy: 'thorough_single',
54
+ reason: 'sequential_chain',
55
+ dag_width,
56
+ max_complexity,
57
+ dagContext,
58
+ };
59
+ }
60
+ return {
61
+ strategy: 'quick_single',
62
+ reason: 'sequential_chain',
63
+ dag_width,
64
+ max_complexity,
65
+ dagContext,
66
+ };
67
+ }
68
+
69
+ // 동일 에이전트 + 모두 S: 프롬프트 병합 -> batch single
70
+ if (allSameAgent && allSmall) {
71
+ return {
72
+ strategy: 'batch_single',
73
+ reason: 'same_agent_small_batch',
74
+ dag_width,
75
+ max_complexity,
76
+ dagContext,
77
+ };
78
+ }
79
+
80
+ // dag_width >= 2: 팀
81
+ if (thorough || isHighComplexity) {
82
+ return {
83
+ strategy: 'thorough_team',
84
+ reason: 'parallel_high_complexity',
85
+ dag_width,
86
+ max_complexity,
87
+ dagContext,
88
+ };
89
+ }
90
+ return {
91
+ strategy: 'quick_team',
92
+ reason: 'parallel_low_complexity',
93
+ dag_width,
94
+ max_complexity,
95
+ dagContext,
96
+ };
97
+ }
98
+
99
+ /**
100
+ * DAG 정보 계산 — 레벨별 태스크 배열, 간선, 최대 폭
101
+ * @param {Array<{id:string, depends_on?:string[]}>} subtasks
102
+ * @param {string} graph_type
103
+ * @returns {{ width: number, levels: Record<number, string[]>, edges: Array<{from:string, to:string}> }}
104
+ */
105
+ function computeDagInfo(subtasks, graph_type) {
106
+ if (graph_type === 'SEQUENTIAL') {
107
+ const levels = {};
108
+ const edges = [];
109
+ subtasks.forEach((t, i) => {
110
+ levels[i] = [t.id];
111
+ if (i > 0) edges.push({ from: subtasks[i - 1].id, to: t.id });
112
+ });
113
+ return { width: 1, levels, edges };
114
+ }
115
+ if (graph_type === 'INDEPENDENT') {
116
+ const levels = { 0: subtasks.map((t) => t.id) };
117
+ return { width: subtasks.length, levels, edges: [] };
118
+ }
119
+
120
+ // DAG: 레벨별 계산 (순환 의존 방어)
121
+ const taskLevels = {};
122
+ const visiting = new Set();
123
+
124
+ function getLevel(task) {
125
+ if (taskLevels[task.id] !== undefined) return taskLevels[task.id];
126
+ if (visiting.has(task.id)) {
127
+ taskLevels[task.id] = 0; // 순환 끊기
128
+ return 0;
129
+ }
130
+ if (!task.depends_on || task.depends_on.length === 0) {
131
+ taskLevels[task.id] = 0;
132
+ return 0;
133
+ }
134
+ visiting.add(task.id);
135
+ const depLevels = task.depends_on.map((depId) => {
136
+ const dep = subtasks.find((s) => s.id === depId);
137
+ return dep ? getLevel(dep) : 0;
138
+ });
139
+ visiting.delete(task.id);
140
+ taskLevels[task.id] = Math.max(...depLevels) + 1;
141
+ return taskLevels[task.id];
142
+ }
143
+
144
+ subtasks.forEach(getLevel);
145
+
146
+ // 레벨별 태스크 그룹핑
147
+ const levels = {};
148
+ for (const [id, level] of Object.entries(taskLevels)) {
149
+ if (!levels[level]) levels[level] = [];
150
+ levels[level].push(id);
151
+ }
152
+
153
+ // 간선 수집
154
+ const edges = [];
155
+ for (const task of subtasks) {
156
+ if (task.depends_on) {
157
+ for (const depId of task.depends_on) {
158
+ edges.push({ from: depId, to: task.id });
159
+ }
160
+ }
161
+ }
162
+
163
+ const width = Math.max(...Object.values(levels).map((arr) => arr.length), 1);
164
+ return { width, levels, edges };
165
+ }
166
+
167
+ /**
168
+ * 선행 태스크의 결과를 dagContext.edges에서 조회하여 반환
169
+ * @param {string} taskId - 조회 대상 태스크 ID
170
+ * @param {{ dagContext?: { edges: Array<{from:string, to:string}>, taskResults: Record<string, *> } }} pipelineState
171
+ * @returns {Record<string, *>} 선행 태스크 ID → 결과 매핑
172
+ */
173
+ export function getUpstreamResults(taskId, pipelineState) {
174
+ const ctx = pipelineState?.dagContext;
175
+ if (!ctx) return {};
176
+ const upstreamIds = ctx.edges.filter((e) => e.to === taskId).map((e) => e.from);
177
+ const results = {};
178
+ for (const id of upstreamIds) {
179
+ if (id in (ctx.taskResults || {})) {
180
+ results[id] = ctx.taskResults[id];
181
+ }
182
+ }
183
+ return results;
184
+ }
185
+
186
+ /**
187
+ * 태스크 완료 시 결과를 dagContext에 기록
188
+ * @param {string} taskId - 완료된 태스크 ID
189
+ * @param {*} result - 태스크 결과
190
+ * @param {{ dagContext?: { taskResults: Record<string, *> } }} pipelineState
191
+ * @returns {boolean} 기록 성공 여부
192
+ */
193
+ export function updateTaskResult(taskId, result, pipelineState) {
194
+ const ctx = pipelineState?.dagContext;
195
+ if (!ctx) return false;
196
+ if (!ctx.taskResults) ctx.taskResults = {};
197
+ ctx.taskResults[taskId] = result;
198
+ return true;
199
+ }
200
+
201
+ /**
202
+ * 최대 복잡도 추출
203
+ * @param {Array<{complexity?:string}>} subtasks
204
+ * @returns {"S" | "M" | "L" | "XL"}
205
+ */
206
+ function getMaxComplexity(subtasks) {
207
+ const order = { S: 0, M: 1, L: 2, XL: 3 };
208
+ let max = 'S';
209
+ for (const s of subtasks) {
210
+ const complexity = normalizeComplexity(s.complexity);
211
+ if (order[complexity] > order[max]) max = complexity;
212
+ }
213
+ return max;
214
+ }
215
+
216
+ /**
217
+ * complexity 기본값 보정
218
+ * @param {string | undefined} complexity
219
+ * @returns {"S" | "M" | "L" | "XL"}
220
+ */
221
+ function normalizeComplexity(complexity) {
222
+ return ['S', 'M', 'L', 'XL'].includes(complexity) ? complexity : 'M';
223
+ }