loadtoagent 1.1.0 → 1.3.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 (83) hide show
  1. package/README.ko.md +7 -0
  2. package/README.md +7 -0
  3. package/README.zh-CN.md +7 -0
  4. package/docs/PROVIDER-CONTRACTS.md +23 -1
  5. package/docs/UI-AUDIT-100.md +118 -0
  6. package/docs/UI-AUDIT-101-200.md +120 -0
  7. package/docs/UI-AUDIT-201-300.md +120 -0
  8. package/main.js +135 -38
  9. package/package.json +13 -4
  10. package/preload.js +6 -0
  11. package/renderer/app-agent-actions.js +125 -53
  12. package/renderer/app-bootstrap.js +54 -19
  13. package/renderer/app-dashboard.js +190 -55
  14. package/renderer/app-drawer-content.js +48 -44
  15. package/renderer/app-drawer-data.js +26 -13
  16. package/renderer/app-drawer.js +72 -54
  17. package/renderer/app-events-dialogs.js +146 -37
  18. package/renderer/app-events-filters.js +172 -13
  19. package/renderer/app-events-navigation.js +77 -30
  20. package/renderer/app-events-sessions.js +156 -9
  21. package/renderer/app-events.js +2 -1
  22. package/renderer/app-graph-model.js +20 -38
  23. package/renderer/app-graph-orchestration.js +15 -13
  24. package/renderer/app-graph-view.js +228 -113
  25. package/renderer/app-management.js +211 -0
  26. package/renderer/app-provider-visibility.js +124 -0
  27. package/renderer/app-quality.js +568 -0
  28. package/renderer/app-run-modal.js +103 -33
  29. package/renderer/app-runtime-overview.js +312 -0
  30. package/renderer/app-session-render.js +94 -37
  31. package/renderer/app-tmux-render.js +52 -44
  32. package/renderer/app.js +153 -75
  33. package/renderer/i18n-messages.js +833 -16
  34. package/renderer/i18n.js +104 -0
  35. package/renderer/index.html +145 -59
  36. package/renderer/shared.js +17 -0
  37. package/renderer/styles-agent-map.css +6 -0
  38. package/renderer/styles-cards.css +26 -0
  39. package/renderer/styles-components.css +86 -9
  40. package/renderer/styles-management.css +355 -0
  41. package/renderer/styles-overlays.css +8 -2
  42. package/renderer/styles-product.css +24 -16
  43. package/renderer/styles-quality.css +312 -0
  44. package/renderer/styles-readability.css +862 -0
  45. package/renderer/styles-responsive-product.css +84 -12
  46. package/renderer/styles-responsive-runtime.css +22 -14
  47. package/renderer/styles-responsive-shell.css +44 -48
  48. package/renderer/styles-responsive-workflows.css +37 -3
  49. package/renderer/styles-run-composer.css +5 -0
  50. package/renderer/styles-runtime-overview.css +285 -0
  51. package/renderer/styles-settings.css +160 -0
  52. package/renderer/styles-terminal.css +339 -2
  53. package/renderer/styles-workflow-map.css +362 -15
  54. package/renderer/styles-workflows.css +69 -2
  55. package/renderer/styles.css +27 -12
  56. package/renderer/terminal-agent.js +17 -13
  57. package/renderer/terminal-events.js +233 -40
  58. package/renderer/terminal-workbench.js +165 -77
  59. package/renderer/terminal.js +341 -34
  60. package/src/agentMonitor/claudeParser.js +96 -7
  61. package/src/agentMonitor/codexParser.js +59 -4
  62. package/src/agentMonitor/executionActivity.js +282 -0
  63. package/src/agentMonitor/genericParser.js +56 -13
  64. package/src/agentMonitor/hierarchy.js +17 -0
  65. package/src/agentMonitor/responseIntent.js +51 -0
  66. package/src/agentMonitor.js +21 -3
  67. package/src/agentRunner.js +66 -1
  68. package/src/attentionNotifier.js +14 -10
  69. package/src/automationMonitor.js +258 -0
  70. package/src/contracts.js +10 -1
  71. package/src/ipc/registerAgentIpc.js +9 -3
  72. package/src/ipc/registerAppIpc.js +4 -1
  73. package/src/ipc/registerTerminalIpc.js +12 -6
  74. package/src/macUpdateHelper.js +210 -0
  75. package/src/monitorWorker.js +65 -6
  76. package/src/platformPath.js +80 -0
  77. package/src/processMonitor.js +80 -22
  78. package/src/providerVisibilityStore.js +45 -0
  79. package/src/sessionIntelligence.js +247 -0
  80. package/src/terminalHost.js +381 -0
  81. package/src/terminalHostDaemon.js +60 -0
  82. package/src/terminalManager.js +158 -3
  83. package/src/updateInstaller.js +175 -0
@@ -3,6 +3,7 @@
3
3
  window.LoadToAgentAppFactories = window.LoadToAgentAppFactories || {};
4
4
 
5
5
  window.LoadToAgentAppFactories.createGraphModel = function createGraphModel(context = {}) {
6
+ const t = (key, params) => window.LoadToAgentI18n.t(key, params);
6
7
  const {
7
8
  $,
8
9
  esc,
@@ -78,10 +79,10 @@ window.LoadToAgentAppFactories.createGraphModel = function createGraphModel(cont
78
79
  if (tmux)
79
80
  return {
80
81
  kind: "tmux",
81
- label: "TMUX 사용",
82
- detail: [tmux.distro, tmux.sessionName, tmux.paneNativeId || tmux.paneId].filter(Boolean).join(" · ") || "분할 터미널에서 실행",
82
+ label: t("graph.tmux_used"),
83
+ detail: [tmux.distro, tmux.sessionName, tmux.paneNativeId || tmux.paneId].filter(Boolean).join(" · ") || t("graph.running_in_split_terminal"),
83
84
  };
84
- return { kind: "standard", label: "일반 실행", detail: "TMUX 미사용" };
85
+ return { kind: "standard", label: t("graph.standard_run"), detail: t("graph.tmux_not_used") };
85
86
  }
86
87
 
87
88
  function executionModeBadge(session, compact = false) {
@@ -103,49 +104,30 @@ window.LoadToAgentAppFactories.createGraphModel = function createGraphModel(cont
103
104
  return seen.size;
104
105
  }
105
106
 
106
- function runtimeAgentSummary(model, entries = []) {
107
+ function runtimeAgentSummary(model, tmuxEntries = []) {
107
108
  const liveNodes = model.nodes.filter(isLiveSession);
108
109
  const liveById = new Map(liveNodes.map((session) => [session.id, session]));
109
- const activeEntries = entries.filter((entry) => entry && entry.pane && !entry.pane.dead);
110
- const tmuxKeys = new Set();
111
- const tmuxSessionIds = new Set();
112
- const paneKeys = new Map();
113
-
114
- for (const entry of activeEntries) {
115
- const linkedSessionId = String(entry.agent && entry.agent.linkedSessionId || "");
116
- if (linkedSessionId && liveById.has(linkedSessionId)) {
117
- tmuxSessionIds.add(linkedSessionId);
118
- tmuxKeys.add(`session:${linkedSessionId}`);
119
- continue;
120
- }
121
- const paneId = String(entry.pane.nativeId || entry.pane.id || "");
122
- const distroId = String(entry.distro && (entry.distro.id || entry.distro.name) || "");
123
- if (paneId) {
124
- const key = `pane:${distroId}:${paneId}`;
125
- tmuxKeys.add(key);
126
- paneKeys.set(String(entry.pane.id || ""), key);
127
- paneKeys.set(String(entry.pane.nativeId || ""), key);
128
- }
129
- }
130
-
110
+ const tmuxSessionIds = new Set(
111
+ tmuxEntries
112
+ .filter((entry) => entry && entry.pane && !entry.pane.dead)
113
+ .map((entry) => String(entry.agent && entry.agent.linkedSessionId || ""))
114
+ .filter((id) => id && liveById.has(id)),
115
+ );
131
116
  for (const session of liveNodes) {
132
- const presence = (session.runtimePresence || []).find((item) => item.kind === "tmux");
133
- if (!presence) continue;
134
- tmuxSessionIds.add(session.id);
135
- const paneKey = [presence.paneId, presence.paneNativeId, presence.nativeId]
136
- .map((value) => paneKeys.get(String(value || "")))
137
- .find(Boolean);
138
- tmuxKeys.add(paneKey || `session:${session.id}`);
117
+ if (agentExecutionMode(session).kind === "tmux") tmuxSessionIds.add(session.id);
139
118
  }
140
-
141
- const standardCount = liveNodes.filter((session) => !tmuxSessionIds.has(session.id)).length;
142
- const tmuxCount = tmuxKeys.size;
119
+ const tmuxCount = liveNodes.filter((session) => tmuxSessionIds.has(session.id)).length;
120
+ const runningExecutions = liveNodes.flatMap((session) => (session.executions || []).filter((activity) => activity.status === "running"));
143
121
  return {
144
- activeCount: standardCount + tmuxCount,
145
- standardCount,
122
+ activeCount: liveNodes.length,
123
+ standardCount: liveNodes.length - tmuxCount,
146
124
  tmuxCount,
125
+ rootCount: liveNodes.filter((session) => !session.parentId).length,
147
126
  activeHelperCount: liveNodes.filter((session) => session.parentId).length,
148
127
  helperRecordCount: model.nodes.filter((session) => session.parentId).length,
128
+ runningExecutionCount: runningExecutions.length,
129
+ shellExecutionCount: runningExecutions.filter((activity) => activity.kind === "shell").length,
130
+ backgroundExecutionCount: runningExecutions.filter((activity) => activity.mode === "background" || activity.kind === "background").length,
149
131
  };
150
132
  }
151
133
 
@@ -13,12 +13,13 @@ window.LoadToAgentAppFactories.createGraphOrchestration = function createGraphOr
13
13
  graphPath,
14
14
  connectedGraphSessions,
15
15
  sortGraphNodes,
16
- liveTmuxEntries,
17
16
  runtimeAgentSummary,
17
+ liveTmuxEntries,
18
18
  runtimeSeparatedOverview,
19
19
  focusedGraph,
20
20
  scheduleAgentWorkflowConnections,
21
21
  } = context;
22
+ const t = (key, params) => window.LoadToAgentI18n.t(key, params);
22
23
 
23
24
  function renderAgentMap(sessions, motionKind = "refresh") {
24
25
  const model = connectedGraphSessions(sessions);
@@ -36,7 +37,7 @@ window.LoadToAgentAppFactories.createGraphOrchestration = function createGraphOr
36
37
  if (focus) {
37
38
  $("#liveSessionGrid").innerHTML = focusedGraph(focus, model, motionKind);
38
39
  const path = graphPath(focus, model.byId);
39
- $("#graphBreadcrumbs").innerHTML = `<button type="button" data-graph-reset>작업 목록</button>${path
40
+ $("#graphBreadcrumbs").innerHTML = `<button type="button" data-graph-reset>${esc(t("graph.task_list"))}</button>${path
40
41
  .map((item) => {
41
42
  const label = item.parentId ? item.agentName || agentRoleLabel(item.agentRole) : item.title;
42
43
  const preview = readablePreview(label, item.parentId ? 42 : 72);
@@ -49,28 +50,29 @@ window.LoadToAgentAppFactories.createGraphOrchestration = function createGraphOr
49
50
  $("#graphResetBtn").classList.remove("hidden");
50
51
  scheduleAgentWorkflowConnections();
51
52
  } else {
52
- const tmuxEntries = liveTmuxEntries();
53
- const runtime = runtimeAgentSummary(model, tmuxEntries);
54
- $("#liveSessionGrid").innerHTML = `<details class="runtime-disclosure" open>
53
+ const runtime = runtimeAgentSummary(model, liveTmuxEntries(state.snapshot && state.snapshot.tmux));
54
+ $("#liveSessionGrid").innerHTML = `<details class="runtime-disclosure" data-disclosure-key="home:runtime-overview" open>
55
55
  <summary>
56
56
  <span>
57
- <b>${runtime.activeCount}개 AI가 작업 중입니다</b>
58
- <small>일반 실행 AI ${runtime.standardCount}개와 TMUX AI ${runtime.tmuxCount}개를 합산했습니다. 작업 도움 AI ${runtime.activeHelperCount}개는 수에 포함됩니다.</small>
57
+ <b>${esc(t("graph.ai_working_count", { count: runtime.activeCount }))}</b>
58
+ <small>${esc(t("graph.runtime_count_explanation", { standard: runtime.standardCount, tmux: runtime.tmuxCount, helpers: runtime.activeHelperCount }))}${runtime.runningExecutionCount ? ` · ${esc(t("graph.runtime_execution_count", { shell: runtime.shellExecutionCount, background: runtime.backgroundExecutionCount }))}` : ""}</small>
59
59
  </span>
60
- <em>상세 흐름 보기 <i aria-hidden="true">↓</i>
60
+ <em>${esc(t("graph.view_detailed_flow"))} <i aria-hidden="true">↓</i>
61
61
  </em>
62
62
  </summary>${runtimeSeparatedOverview(roots, model)}</details>`;
63
63
  $("#graphBreadcrumbs").innerHTML =
64
64
  `<span class="map-hint">
65
- 일반 실행 AI <b>${runtime.standardCount}</b>개 ·
66
- TMUX AI <b>${runtime.tmuxCount}</b>개 ·
67
- 작업 중 도움 AI <b>${runtime.activeHelperCount}</b>개 ·
68
- 도움 AI 기록 <b>${runtime.helperRecordCount}</b>개
65
+ ${esc(t("graph.standard_ai"))} <b>${runtime.standardCount}</b> ·
66
+ ${esc(t("graph.tmux_ai"))} <b>${runtime.tmuxCount}</b> ·
67
+ ${esc(t("graph.active_helper_ai"))} <b>${runtime.activeHelperCount}</b> ·
68
+ ${esc(t("graph.helper_ai_history"))} <b>${runtime.helperRecordCount}</b> ·
69
+ ${esc(t("graph.running_shell"))} <b>${runtime.shellExecutionCount}</b> ·
70
+ ${esc(t("graph.running_background"))} <b>${runtime.backgroundExecutionCount}</b>
69
71
  </span>`;
70
72
  $("#graphResetBtn").classList.add("hidden");
71
73
  return runtime.activeCount;
72
74
  }
73
- return model.nodes.filter(isLiveSession).length + liveTmuxEntries().filter((entry) => !entry.agent.linkedSessionId).length;
75
+ return model.nodes.filter(isLiveSession).length;
74
76
  }
75
77
 
76
78
  return { renderAgentMap };