loadtoagent 1.0.0 → 1.1.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/main.js +50 -1
- package/package.json +4 -2
- package/preload.js +5 -0
- package/renderer/app-bootstrap.js +11 -1
- package/renderer/app-dashboard.js +7 -3
- package/renderer/app-drawer-content.js +68 -55
- package/renderer/app-drawer.js +13 -7
- package/renderer/app-events-filters.js +5 -1
- package/renderer/app-events-navigation.js +1 -1
- package/renderer/app-events-sessions.js +21 -1
- package/renderer/app-graph-model.js +47 -1
- package/renderer/app-graph-orchestration.js +9 -8
- package/renderer/app-graph-view.js +6 -5
- package/renderer/app-tmux-render.js +75 -2
- package/renderer/app.js +2 -1
- package/renderer/i18n-messages.js +1 -0
- package/renderer/index.html +18 -17
- package/renderer/styles-agent-map.css +44 -1
- package/renderer/styles-collaboration.css +18 -88
- package/renderer/styles-components.css +40 -5
- package/renderer/styles-overlays.css +5 -0
- package/renderer/styles-responsive-runtime.css +9 -0
- package/renderer/styles-responsive-workflows.css +0 -14
- package/renderer/styles-tmux.css +154 -0
- package/renderer/terminal-workbench.js +11 -1
- package/renderer/terminal.js +9 -3
- package/src/attentionNotifier.js +67 -0
- package/src/processMonitor.js +1 -1
- package/src/tmuxMonitor.js +2 -2
|
@@ -209,7 +209,7 @@ window.LoadToAgentAppFactories.createGraphView = function createGraphView(contex
|
|
|
209
209
|
for (const tmuxSession of distro.sessions || []) {
|
|
210
210
|
for (const window of tmuxSession.windows || []) {
|
|
211
211
|
for (const pane of window.panes || []) {
|
|
212
|
-
if (!pane.agent) continue;
|
|
212
|
+
if (!pane.agent || pane.dead) continue;
|
|
213
213
|
entries.push({ distro, tmuxSession, window, pane, agent: pane.agent });
|
|
214
214
|
}
|
|
215
215
|
}
|
|
@@ -267,13 +267,14 @@ window.LoadToAgentAppFactories.createGraphView = function createGraphView(contex
|
|
|
267
267
|
const tmuxEntries = liveTmuxEntries(tmux);
|
|
268
268
|
const tmuxLinkedIds = new Set(tmuxEntries.map((entry) => entry.agent.linkedSessionId).filter(Boolean));
|
|
269
269
|
const tmuxRoots = roots.filter((root) => agentExecutionMode(root).kind === "tmux");
|
|
270
|
-
const standardRoots = roots.filter((root) => agentExecutionMode(root).kind !== "tmux");
|
|
270
|
+
const standardRoots = roots.filter((root) => agentExecutionMode(root).kind !== "tmux" && !tmuxLinkedIds.has(root.id));
|
|
271
271
|
const providerOrder = [...new Set([...state.providers.map((item) => item.id), ...roots.map((item) => item.provider)])];
|
|
272
272
|
const lanesFor = (items) =>
|
|
273
273
|
providerOrder.map((providerId) => ({ providerId, roots: items.filter((root) => root.provider === providerId) })).filter((item) => item.roots.length);
|
|
274
274
|
const standardLanes = lanesFor(standardRoots);
|
|
275
|
-
const
|
|
276
|
-
const
|
|
275
|
+
const fallbackTmuxRoots = tmuxRoots.filter((root) => !tmuxLinkedIds.has(root.id));
|
|
276
|
+
const fallbackTmuxLanes = lanesFor(fallbackTmuxRoots);
|
|
277
|
+
const tmuxDisplayCount = tmuxEntries.length + fallbackTmuxRoots.length;
|
|
277
278
|
const standardHtml = standardLanes.length
|
|
278
279
|
? `<div class="agent-flow-overview">${standardLanes.map((item) => providerFlowLane(item.providerId, item.roots, model)).join("")}</div>`
|
|
279
280
|
: '<div class="runtime-segment-empty"><b>일반 실행 AI가 없습니다</b><span>현재 감지된 작업은 모두 TMUX에서 실행 중입니다.</span></div>';
|
|
@@ -293,7 +294,7 @@ window.LoadToAgentAppFactories.createGraphView = function createGraphView(contex
|
|
|
293
294
|
<header>
|
|
294
295
|
<span class="runtime-segment-icon">▦</span>
|
|
295
296
|
<span><small>TMUX 전용</small><b>TMUX 세션</b><em>Linux 작업 묶음·창·분할 칸을 유지해서 실행 중인 AI</em></span>
|
|
296
|
-
<strong>${
|
|
297
|
+
<strong>${tmuxDisplayCount}개</strong>
|
|
297
298
|
<button type="button" class="live-tmux-overview-open">TMUX 전체 화면 →</button>
|
|
298
299
|
</header>
|
|
299
300
|
${tmuxHtml}
|
|
@@ -3,7 +3,20 @@
|
|
|
3
3
|
window.LoadToAgentAppFactories = window.LoadToAgentAppFactories || {};
|
|
4
4
|
|
|
5
5
|
window.LoadToAgentAppFactories.createTmuxRenderer = function createTmuxRenderer(context = {}) {
|
|
6
|
-
const {
|
|
6
|
+
const {
|
|
7
|
+
$,
|
|
8
|
+
esc,
|
|
9
|
+
state,
|
|
10
|
+
compact,
|
|
11
|
+
providerInfo,
|
|
12
|
+
providerStyle,
|
|
13
|
+
agentRoleLabel,
|
|
14
|
+
subagentWorkState,
|
|
15
|
+
subagentWorkLabel,
|
|
16
|
+
latestWorkCopy,
|
|
17
|
+
readablePreview,
|
|
18
|
+
timeAgo,
|
|
19
|
+
} = context;
|
|
7
20
|
|
|
8
21
|
function tmuxEntities(tmux) {
|
|
9
22
|
const distros = new Map();
|
|
@@ -60,6 +73,65 @@ window.LoadToAgentAppFactories.createTmuxRenderer = function createTmuxRenderer(
|
|
|
60
73
|
: [];
|
|
61
74
|
}
|
|
62
75
|
|
|
76
|
+
function linkedTmuxSubagents(agent) {
|
|
77
|
+
if (!agent || !agent.linkedSessionId) return [];
|
|
78
|
+
const sessions = (state.snapshot && state.snapshot.sessions) || [];
|
|
79
|
+
const byId = new Map(sessions.map((session) => [session.id, session]));
|
|
80
|
+
const root = byId.get(agent.linkedSessionId);
|
|
81
|
+
const queue = (root && root.childIds || agent.childIds || []).map((id) => ({ id, depth: 1 }));
|
|
82
|
+
const seen = new Set(root ? [root.id] : []);
|
|
83
|
+
const children = [];
|
|
84
|
+
for (let cursor = 0; cursor < queue.length; cursor += 1) {
|
|
85
|
+
const item = queue[cursor];
|
|
86
|
+
if (!item.id || seen.has(item.id)) continue;
|
|
87
|
+
seen.add(item.id);
|
|
88
|
+
const child = byId.get(item.id);
|
|
89
|
+
if (!child) continue;
|
|
90
|
+
children.push({ session: child, depth: item.depth });
|
|
91
|
+
for (const childId of child.childIds || []) queue.push({ id: childId, depth: item.depth + 1 });
|
|
92
|
+
}
|
|
93
|
+
return children;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function tmuxSubagentPanel(pane, agent) {
|
|
97
|
+
const children = linkedTmuxSubagents(agent);
|
|
98
|
+
if (!children.length) return "";
|
|
99
|
+
const expanded = state.expandedTmuxSubagents.has(pane.id);
|
|
100
|
+
const listId = `tmux-subagents-list-${encodeURIComponent(pane.id)}`;
|
|
101
|
+
const working = children.filter(({ session }) => subagentWorkState(session) === "working").length;
|
|
102
|
+
const attention = children.filter(({ session }) => subagentWorkState(session) === "attention").length;
|
|
103
|
+
const statusSummary = [
|
|
104
|
+
working ? `${working}개 작업 중` : "",
|
|
105
|
+
attention ? `${attention}개 확인 필요` : "",
|
|
106
|
+
].filter(Boolean).join(" · ") || "현재 모두 쉬는 중";
|
|
107
|
+
const rows = children
|
|
108
|
+
.map(({ session, depth }) => {
|
|
109
|
+
const provider = providerInfo(session.provider);
|
|
110
|
+
const role = session.agentName || agentRoleLabel(session.agentRole);
|
|
111
|
+
const assigned = session.delegation && session.delegation.assignment || session.taskName || session.title || "담당 작업 확인 중";
|
|
112
|
+
const work = readablePreview(latestWorkCopy(session) || session.statusDetail || "상태 확인 중", 96);
|
|
113
|
+
const workState = subagentWorkState(session);
|
|
114
|
+
return `<article class="tmux-subagent-row work-${workState}" data-tmux-subagent-id="${esc(session.id)}"
|
|
115
|
+
style="${providerStyle(session.provider)};--tmux-subagent-depth:${Math.min(2, Math.max(0, depth - 1))}">
|
|
116
|
+
<span class="provider-mark" aria-hidden="true">${esc(provider.mark)}</span>
|
|
117
|
+
<span class="tmux-subagent-copy">
|
|
118
|
+
<span><b>${esc(role)}</b><i>${esc(subagentWorkLabel(session))}</i><small>${esc(timeAgo(session.updatedAt))}</small></span>
|
|
119
|
+
<strong>${esc(assigned)}</strong>
|
|
120
|
+
<em title="${esc(work.full)}">${esc(work.text)}</em>
|
|
121
|
+
</span>
|
|
122
|
+
<button type="button" data-open-subagent-chat="${esc(session.id)}" aria-label="${esc(`${role} · ${assigned} 대화 보기`)}">대화 보기 ↗</button>
|
|
123
|
+
</article>`;
|
|
124
|
+
})
|
|
125
|
+
.join("");
|
|
126
|
+
return `<section class="tmux-subagents ${expanded ? "expanded" : ""}" data-tmux-subagents="${esc(pane.id)}">
|
|
127
|
+
<button type="button" class="tmux-subagents-toggle" data-tmux-subagents-toggle="${esc(pane.id)}" aria-expanded="${expanded}" aria-controls="${esc(listId)}">
|
|
128
|
+
<span><b>연결된 도움 AI ${children.length}개</b><small>${statusSummary} · tmux 메인 세션 기준</small></span>
|
|
129
|
+
<i aria-hidden="true">↓</i>
|
|
130
|
+
</button>
|
|
131
|
+
<div id="${esc(listId)}" class="tmux-subagent-list ${expanded ? "" : "hidden"}">${rows}</div>
|
|
132
|
+
</section>`;
|
|
133
|
+
}
|
|
134
|
+
|
|
63
135
|
function tmuxPaneCard(pane) {
|
|
64
136
|
const agent = pane.agent;
|
|
65
137
|
const provider = agent && providerInfo(agent.provider);
|
|
@@ -103,6 +175,7 @@ window.LoadToAgentAppFactories.createTmuxRenderer = function createTmuxRenderer(
|
|
|
103
175
|
: '<span class="tmux-shell-note">AI가 아닌 일반 명령창입니다.</span>'
|
|
104
176
|
}
|
|
105
177
|
</button>
|
|
178
|
+
${tmuxSubagentPanel(pane, agent)}
|
|
106
179
|
<footer>
|
|
107
180
|
<span>${agent ? (agent.linkedSessionId ? "대화 기록과 연결됨" : "AI가 실행 중인 것을 확인함") : pane.title || "명령창"}</span>
|
|
108
181
|
<span class="tmux-pane-actions">
|
|
@@ -243,5 +316,5 @@ window.LoadToAgentAppFactories.createTmuxRenderer = function createTmuxRenderer(
|
|
|
243
316
|
.join("");
|
|
244
317
|
}
|
|
245
318
|
|
|
246
|
-
return { tmuxEntities, tmuxFocusPath, tmuxPaneCard, tmuxWindowTree, tmuxSessionTree, filteredTmuxDistros, renderTmuxMap };
|
|
319
|
+
return { tmuxEntities, tmuxFocusPath, linkedTmuxSubagents, tmuxPaneCard, tmuxWindowTree, tmuxSessionTree, filteredTmuxDistros, renderTmuxMap };
|
|
247
320
|
};
|
package/renderer/app.js
CHANGED
|
@@ -28,6 +28,7 @@ window.LoadToAgentAppFactories.createCore = function createCore(context = {}) {
|
|
|
28
28
|
graphFocusId: null,
|
|
29
29
|
graphExpandedProviders: new Set(),
|
|
30
30
|
expandedCompletedSubagents: new Set(),
|
|
31
|
+
expandedTmuxSubagents: new Set(),
|
|
31
32
|
tmuxFocus: null,
|
|
32
33
|
agentCommandDrafts: new Map(),
|
|
33
34
|
agentCommandTargets: new Map(),
|
|
@@ -277,7 +278,7 @@ window.LoadToAgentAppFactories.createCore = function createCore(context = {}) {
|
|
|
277
278
|
function restoreDialogTrigger() {
|
|
278
279
|
const trigger = motionState.activeDialogTrigger;
|
|
279
280
|
motionState.activeDialogTrigger = null;
|
|
280
|
-
if (trigger && trigger.isConnected) trigger.focus();
|
|
281
|
+
if (trigger && trigger.isConnected) trigger.focus({ preventScroll: true });
|
|
281
282
|
}
|
|
282
283
|
window.LoadToAgentA11y = { rememberDialogTrigger, restoreDialogTrigger };
|
|
283
284
|
function readablePreview(value, maxCharacters = 120) {
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"common.send": {"ko":"보내기","en":"Send","zh-CN":"发送"},
|
|
29
29
|
"drawer.title": {"ko":"작업 자세히 보기","en":"View task details","zh-CN":"查看任务详情"},
|
|
30
30
|
"filter.result_summary": {"ko":"{providers} 선택 · {count}개 결과","en":"{providers} selected · {count} results","zh-CN":"已选择 {providers} · {count} 条结果"},
|
|
31
|
+
"filter.applied": {"ko":"필터 적용","en":"Filter applied","zh-CN":"已应用筛选"},
|
|
31
32
|
"guide.steps_remaining": {"ko":"{count}단계 남았어요. 하나씩 눌러 직접 둘러보세요.","en":"{count} steps left. Try each one to explore the app.","zh-CN":"还剩 {count} 步。请逐项点击体验。"},
|
|
32
33
|
"provider.assign": {"ko":"{provider}에게 맡기기","en":"Assign to {provider}","zh-CN":"交给 {provider}"},
|
|
33
34
|
"provider.install_guide": {"ko":"{provider} 설치 안내","en":"{provider} setup guide","zh-CN":"{provider} 安装指南"},
|
package/renderer/index.html
CHANGED
|
@@ -78,6 +78,24 @@
|
|
|
78
78
|
</div>
|
|
79
79
|
</header>
|
|
80
80
|
|
|
81
|
+
<section id="beginnerGuide" class="beginner-guide" aria-labelledby="beginnerGuideTitle">
|
|
82
|
+
<div class="beginner-guide-intro">
|
|
83
|
+
<span class="guide-time" data-i18n="ui.first_10_minutes">첫 10분 코스</span>
|
|
84
|
+
<b id="beginnerGuideTitle" data-i18n="ui.these_four_steps_are_all_you_need">이 네 가지만 익히면 충분해요</b>
|
|
85
|
+
<span id="guideProgressText" data-i18n="ui.try_each_step_to_explore_the_app">하나씩 눌러 직접 둘러보세요.</span>
|
|
86
|
+
<div class="guide-progress" role="progressbar" aria-label="시작 가이드 진행률" data-i18n-aria-label="ui.quick_start_progress" aria-valuemin="0" aria-valuemax="4" aria-valuenow="0"><i id="guideProgressBar"></i></div>
|
|
87
|
+
</div>
|
|
88
|
+
<ol>
|
|
89
|
+
<li data-guide-step="create"><button type="button" data-guide-action="create"><i>1</i><span><b data-i18n="ui.assign_work_to_ai">AI에게 일 맡기기</b><small data-i18n="ui.choose_a_task_and_workspace_to_get_started">할 일과 작업 폴더를 고르면 바로 시작돼요.</small><em data-i18n="ui.try_it">직접 해보기 →</em></span></button></li>
|
|
90
|
+
<li data-guide-step="active"><button type="button" data-guide-action="active"><i>2</i><span><b data-i18n="ui.check_progress">진행 상황 확인</b><small data-i18n="ui.ai_with_a_green_indicator_is_working_now">초록 표시가 있는 AI는 지금 일하고 있어요.</small><em data-i18n="ui.view_active_work">진행 중 보기 →</em></span></button></li>
|
|
91
|
+
<li data-guide-step="waiting"><button type="button" data-guide-action="waiting"><i>3</i><span><b data-i18n="ui.find_items_to_review">확인할 일 찾기</b><small data-i18n="ui.items_marked_needs_review_need_a_response_or_choice">‘내 확인 필요’ 상태에는 답변이나 선택이 필요해요.</small><em data-i18n="ui.view_review_items">확인할 일 보기 →</em></span></button></li>
|
|
92
|
+
<li data-guide-step="detail"><button type="button" data-guide-action="detail"><i>4</i><span><b data-i18n="drawer.title">작업 자세히 보기</b><small data-i18n="ui.see_conversation_progress_and_usage_in_one_place">대화, 진행 과정, 사용량을 한곳에서 확인해요.</small><em data-i18n="ui.open_a_task">작업 열어보기 →</em></span></button></li>
|
|
93
|
+
</ol>
|
|
94
|
+
<button id="dismissGuideBtn" class="guide-dismiss" type="button" data-i18n="ui.collapse_guide">가이드 접기</button>
|
|
95
|
+
</section>
|
|
96
|
+
|
|
97
|
+
<section id="providerOverview" class="provider-overview" aria-label="AI별 현황" data-i18n-aria-label="ui.status_by_ai"></section>
|
|
98
|
+
|
|
81
99
|
<section id="updateNotice" class="update-notice hidden" aria-live="polite">
|
|
82
100
|
<span class="update-notice-signal" aria-hidden="true"><i></i></span>
|
|
83
101
|
<div><b id="updateNoticeTitle" data-i18n="ui.a_new_version_is_available">새 버전을 사용할 수 있습니다.</b><small id="updateNoticeText" data-i18n="ui.download_the_update_from_settings">설정에서 업데이트 파일을 받을 수 있습니다.</small></div>
|
|
@@ -148,22 +166,6 @@
|
|
|
148
166
|
</div>
|
|
149
167
|
</section>
|
|
150
168
|
|
|
151
|
-
<section id="beginnerGuide" class="beginner-guide" aria-labelledby="beginnerGuideTitle">
|
|
152
|
-
<div class="beginner-guide-intro">
|
|
153
|
-
<span class="guide-time" data-i18n="ui.first_10_minutes">첫 10분 코스</span>
|
|
154
|
-
<b id="beginnerGuideTitle" data-i18n="ui.these_four_steps_are_all_you_need">이 네 가지만 익히면 충분해요</b>
|
|
155
|
-
<span id="guideProgressText" data-i18n="ui.try_each_step_to_explore_the_app">하나씩 눌러 직접 둘러보세요.</span>
|
|
156
|
-
<div class="guide-progress" role="progressbar" aria-label="시작 가이드 진행률" data-i18n-aria-label="ui.quick_start_progress" aria-valuemin="0" aria-valuemax="4" aria-valuenow="0"><i id="guideProgressBar"></i></div>
|
|
157
|
-
</div>
|
|
158
|
-
<ol>
|
|
159
|
-
<li data-guide-step="create"><button type="button" data-guide-action="create"><i>1</i><span><b data-i18n="ui.assign_work_to_ai">AI에게 일 맡기기</b><small data-i18n="ui.choose_a_task_and_workspace_to_get_started">할 일과 작업 폴더를 고르면 바로 시작돼요.</small><em data-i18n="ui.try_it">직접 해보기 →</em></span></button></li>
|
|
160
|
-
<li data-guide-step="active"><button type="button" data-guide-action="active"><i>2</i><span><b data-i18n="ui.check_progress">진행 상황 확인</b><small data-i18n="ui.ai_with_a_green_indicator_is_working_now">초록 표시가 있는 AI는 지금 일하고 있어요.</small><em data-i18n="ui.view_active_work">진행 중 보기 →</em></span></button></li>
|
|
161
|
-
<li data-guide-step="waiting"><button type="button" data-guide-action="waiting"><i>3</i><span><b data-i18n="ui.find_items_to_review">확인할 일 찾기</b><small data-i18n="ui.items_marked_needs_review_need_a_response_or_choice">‘내 확인 필요’ 상태에는 답변이나 선택이 필요해요.</small><em data-i18n="ui.view_review_items">확인할 일 보기 →</em></span></button></li>
|
|
162
|
-
<li data-guide-step="detail"><button type="button" data-guide-action="detail"><i>4</i><span><b data-i18n="drawer.title">작업 자세히 보기</b><small data-i18n="ui.see_conversation_progress_and_usage_in_one_place">대화, 진행 과정, 사용량을 한곳에서 확인해요.</small><em data-i18n="ui.open_a_task">작업 열어보기 →</em></span></button></li>
|
|
163
|
-
</ol>
|
|
164
|
-
<button id="dismissGuideBtn" class="guide-dismiss" type="button" data-i18n="ui.collapse_guide">가이드 접기</button>
|
|
165
|
-
</section>
|
|
166
|
-
|
|
167
169
|
<section id="terminalSection" class="terminal-section hidden" aria-label="명령창 직접 다루기">
|
|
168
170
|
<div class="terminal-section-head">
|
|
169
171
|
<div><span class="terminal-logo">›_</span><div><p class="eyebrow" data-i18n="ui.conversation_and_execution_together">대화와 실행 화면을 한곳에서</p><h2 data-i18n="app.nav.session_terminal">세션 터미널</h2><p id="terminalPlatformExplain" class="section-explain" data-i18n="ui.choose_a_session_on_the_left_to_continue_with_its">왼쪽에서 세션을 고르면 이전 AI 대화와 실시간 터미널을 나란히 보며 그대로 이어서 작업할 수 있습니다.</p></div></div>
|
|
@@ -263,7 +265,6 @@
|
|
|
263
265
|
</section>
|
|
264
266
|
|
|
265
267
|
<section id="globalStats" class="global-stats" aria-label="전체 통계" data-i18n-aria-label="ui.overall_statistics"></section>
|
|
266
|
-
<section id="providerOverview" class="provider-overview" aria-label="AI별 현황" data-i18n-aria-label="ui.status_by_ai"></section>
|
|
267
268
|
|
|
268
269
|
<section id="sessionSection" class="sessions-section">
|
|
269
270
|
<div class="sessions-heading">
|
|
@@ -330,7 +330,50 @@
|
|
|
330
330
|
|
|
331
331
|
.provider-overview-card.selected {
|
|
332
332
|
border-color: color-mix(in srgb,var(--provider) 66%,#344151);
|
|
333
|
-
|
|
333
|
+
background: linear-gradient(145deg,color-mix(in srgb,var(--provider) 15%,#10151f),#0d111a 68%);
|
|
334
|
+
box-shadow: inset 0 0 0 2px color-mix(in srgb,var(--provider) 30%,transparent),0 10px 30px rgba(0,0,0,.28),0 0 24px color-mix(in srgb,var(--provider) 10%,transparent);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
.provider-overview-card.selected:before {
|
|
338
|
+
width: 5px;
|
|
339
|
+
opacity: 1;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
.poc-head-states {
|
|
343
|
+
display: grid;
|
|
344
|
+
justify-items: end;
|
|
345
|
+
gap: 4px;
|
|
346
|
+
margin-left: auto;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
.poc-head-states .poc-state {
|
|
350
|
+
margin-left: 0;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
.poc-filter-state {
|
|
354
|
+
display: none;
|
|
355
|
+
padding: 3px 7px;
|
|
356
|
+
border: 1px solid color-mix(in srgb,var(--provider) 58%,#28483f);
|
|
357
|
+
border-radius: 999px;
|
|
358
|
+
background: color-mix(in srgb,var(--provider) 16%,#0b1515);
|
|
359
|
+
color: color-mix(in srgb,var(--provider) 72%,#eafff8);
|
|
360
|
+
font-size: 9px;
|
|
361
|
+
font-weight: 800;
|
|
362
|
+
white-space: nowrap;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
.poc-filter-state.visible {
|
|
366
|
+
display: inline-flex;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
.provider-overview-card.filter-clicked {
|
|
370
|
+
animation: provider-card-confirm .38s cubic-bezier(.22,1,.36,1);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
@keyframes provider-card-confirm {
|
|
374
|
+
0% { transform: scale(.97); }
|
|
375
|
+
60% { transform: translateY(-3px) scale(1.015); }
|
|
376
|
+
100% { transform: translateY(0) scale(1); }
|
|
334
377
|
}
|
|
335
378
|
|
|
336
379
|
.poc-head strong {
|
|
@@ -336,103 +336,33 @@
|
|
|
336
336
|
font-size: 10px;
|
|
337
337
|
}
|
|
338
338
|
|
|
339
|
-
.subagent-
|
|
339
|
+
.subagent-work-source {
|
|
340
340
|
display: grid;
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
padding: 11px;
|
|
348
|
-
border: 1px solid #263b45;
|
|
349
|
-
border-radius: 10px;
|
|
350
|
-
background: #0c171e;
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
.subagent-conversation-summary small {
|
|
354
|
-
display: block;
|
|
355
|
-
color: #718591;
|
|
356
|
-
font-size: 9px;
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
.subagent-conversation-summary b {
|
|
360
|
-
display: block;
|
|
361
|
-
margin-top: 5px;
|
|
362
|
-
color: #dce8ec;
|
|
363
|
-
font-size: 17px;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
.subagent-conversation-summary>span:nth-child(1) b {
|
|
367
|
-
color: #76dfb8;
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
.subagent-conversation-summary>span:nth-child(2) b {
|
|
371
|
-
color: #8fc8df;
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
.subagent-dialog-row.user .chat-bubble {
|
|
375
|
-
background: #10231e;
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
.subagent-dialog-row.assistant .chat-bubble {
|
|
379
|
-
background: #111d28;
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
.subagent-dialog-row.system .chat-bubble {
|
|
383
|
-
background: #0d151c;
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
.subagent-dialog-list .chat-row.assistant {
|
|
387
|
-
padding-left: 28px;
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
.subagent-dialog-list .chat-row.user {
|
|
391
|
-
padding-right: 28px;
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
.subagent-dialog-row .chat-bubble {
|
|
395
|
-
border-color: #283c46;
|
|
396
|
-
min-width: 0;
|
|
397
|
-
max-width: 100%;
|
|
398
|
-
overflow: hidden;
|
|
341
|
+
gap: 5px;
|
|
342
|
+
margin: 0 0 14px;
|
|
343
|
+
padding: 11px 13px;
|
|
344
|
+
border: 1px solid color-mix(in srgb,var(--drawer-provider) 28%,#263844);
|
|
345
|
+
border-radius: 11px;
|
|
346
|
+
background: color-mix(in srgb,var(--drawer-provider) 6%,#0c151d);
|
|
399
347
|
}
|
|
400
348
|
|
|
401
|
-
.subagent-
|
|
402
|
-
|
|
403
|
-
|
|
349
|
+
.subagent-work-source b {
|
|
350
|
+
color: #dbe8e9;
|
|
351
|
+
font-size: 11px;
|
|
404
352
|
}
|
|
405
353
|
|
|
406
|
-
.subagent-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
white-space: nowrap;
|
|
354
|
+
.subagent-work-source span {
|
|
355
|
+
color: #78909a;
|
|
356
|
+
font-size: 10px;
|
|
357
|
+
line-height: 1.55;
|
|
411
358
|
}
|
|
412
359
|
|
|
413
|
-
.subagent-
|
|
414
|
-
margin-
|
|
415
|
-
padding: 3px 6px;
|
|
416
|
-
border-radius: 6px;
|
|
417
|
-
background: #13242a;
|
|
418
|
-
color: #6fa89b;
|
|
419
|
-
font-size: 8px;
|
|
420
|
-
min-width: 0;
|
|
421
|
-
overflow: hidden;
|
|
422
|
-
text-overflow: ellipsis;
|
|
423
|
-
white-space: nowrap;
|
|
360
|
+
.subagent-coordination {
|
|
361
|
+
margin-top: 16px;
|
|
424
362
|
}
|
|
425
363
|
|
|
426
|
-
.subagent-
|
|
427
|
-
|
|
428
|
-
margin: 6px 0 -2px;
|
|
429
|
-
color: #6b8f8a;
|
|
430
|
-
font-size: 8px;
|
|
431
|
-
font-weight: 750;
|
|
432
|
-
min-width: 0;
|
|
433
|
-
overflow: hidden;
|
|
434
|
-
text-overflow: ellipsis;
|
|
435
|
-
white-space: nowrap;
|
|
364
|
+
.subagent-coordination .subagent-message-preview p {
|
|
365
|
+
margin: 0;
|
|
436
366
|
}
|
|
437
367
|
|
|
438
368
|
.subagent-message-preview {
|
|
@@ -778,14 +778,31 @@ button {
|
|
|
778
778
|
color: #7f8da1;
|
|
779
779
|
white-space: nowrap;
|
|
780
780
|
cursor: pointer;
|
|
781
|
-
transition: color var(--motion-fast) ease, background-color var(--motion-fast) ease, border-color var(--motion-fast) ease;
|
|
781
|
+
transition: color var(--motion-fast) ease, background-color var(--motion-fast) ease, border-color var(--motion-fast) ease, box-shadow var(--motion-fast) ease, transform var(--motion-fast) ease;
|
|
782
782
|
}
|
|
783
783
|
|
|
784
|
-
.provider-filter-
|
|
784
|
+
.provider-filter-mark {
|
|
785
785
|
font-family: "Cascadia Code", Consolas, monospace;
|
|
786
786
|
font-size: 9px;
|
|
787
787
|
}
|
|
788
788
|
|
|
789
|
+
.provider-filter-check {
|
|
790
|
+
display: inline-grid;
|
|
791
|
+
place-items: center;
|
|
792
|
+
width: 0;
|
|
793
|
+
height: 16px;
|
|
794
|
+
border-radius: 50%;
|
|
795
|
+
overflow: hidden;
|
|
796
|
+
background: #53d6aa;
|
|
797
|
+
color: #07130f;
|
|
798
|
+
font-size: 10px;
|
|
799
|
+
font-style: normal;
|
|
800
|
+
font-weight: 900;
|
|
801
|
+
opacity: 0;
|
|
802
|
+
transform: scale(.45);
|
|
803
|
+
transition: width var(--motion-fast) ease, opacity var(--motion-fast) ease, transform var(--motion-fast) ease;
|
|
804
|
+
}
|
|
805
|
+
|
|
789
806
|
.provider-filter-chip b {
|
|
790
807
|
font-size: 10px;
|
|
791
808
|
}
|
|
@@ -796,9 +813,27 @@ button {
|
|
|
796
813
|
}
|
|
797
814
|
|
|
798
815
|
.provider-filter-chip.selected {
|
|
799
|
-
color: #
|
|
800
|
-
border-color: #
|
|
801
|
-
background: rgba(66,207,164,.
|
|
816
|
+
color: #f2fffb;
|
|
817
|
+
border-color: #53d6aa;
|
|
818
|
+
background: linear-gradient(135deg,rgba(66,207,164,.24),rgba(66,207,164,.11));
|
|
819
|
+
box-shadow: inset 0 0 0 1px rgba(119,238,198,.17),0 0 0 2px rgba(66,207,164,.08),0 6px 18px rgba(0,0,0,.22);
|
|
820
|
+
transform: translateY(-1px);
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
.provider-filter-chip.selected .provider-filter-check {
|
|
824
|
+
width: 16px;
|
|
825
|
+
opacity: 1;
|
|
826
|
+
transform: scale(1);
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
.provider-filter-chip.filter-clicked {
|
|
830
|
+
animation: provider-filter-confirm .36s cubic-bezier(.22,1,.36,1);
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
@keyframes provider-filter-confirm {
|
|
834
|
+
0% { transform: scale(.93); }
|
|
835
|
+
55% { transform: scale(1.06); }
|
|
836
|
+
100% { transform: translateY(-1px) scale(1); }
|
|
802
837
|
}
|
|
803
838
|
|
|
804
839
|
.session-grid {
|
|
@@ -153,6 +153,7 @@
|
|
|
153
153
|
|
|
154
154
|
.drawer-backdrop.closing {
|
|
155
155
|
animation: motion-backdrop-out 260ms ease both;
|
|
156
|
+
pointer-events: none;
|
|
156
157
|
}
|
|
157
158
|
|
|
158
159
|
.detail-drawer {
|
|
@@ -176,6 +177,10 @@
|
|
|
176
177
|
box-shadow: -32px 0 88px rgba(0,0,0,.52);
|
|
177
178
|
}
|
|
178
179
|
|
|
180
|
+
.detail-drawer:not(.open) {
|
|
181
|
+
pointer-events: none;
|
|
182
|
+
}
|
|
183
|
+
|
|
179
184
|
.modal-backdrop:not(.hidden) {
|
|
180
185
|
animation: motion-backdrop-in var(--motion-medium) ease both;
|
|
181
186
|
}
|
|
@@ -666,6 +666,15 @@
|
|
|
666
666
|
flex-direction: column;
|
|
667
667
|
}
|
|
668
668
|
|
|
669
|
+
.tmux-subagent-row {
|
|
670
|
+
grid-template-columns: 26px minmax(0,1fr);
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
.tmux-subagent-row>button {
|
|
674
|
+
grid-column: 2;
|
|
675
|
+
justify-self: start;
|
|
676
|
+
}
|
|
677
|
+
|
|
669
678
|
.tmux-pane-actions {
|
|
670
679
|
width: 100%;
|
|
671
680
|
justify-content: flex-start;
|
|
@@ -375,20 +375,6 @@
|
|
|
375
375
|
grid-column: 1/-1;
|
|
376
376
|
}
|
|
377
377
|
|
|
378
|
-
.subagent-conversation-summary {
|
|
379
|
-
grid-template-columns: 1fr;
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
.subagent-dialog-list .chat-row.assistant {
|
|
383
|
-
padding-left: 0;
|
|
384
|
-
padding-right: 0;
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
.subagent-dialog-list .chat-row.user {
|
|
388
|
-
padding-left: 0;
|
|
389
|
-
padding-right: 0;
|
|
390
|
-
}
|
|
391
|
-
|
|
392
378
|
.completed-subagent-list {
|
|
393
379
|
grid-template-columns: 1fr;
|
|
394
380
|
}
|