codex-agent-view 0.4.4 → 0.4.6

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/public/app.js CHANGED
@@ -4,87 +4,107 @@ const SESSION_TOKEN_KEY = "codex-agent-view-access-token";
4
4
  const EXCLUDED_SESSION_KEY = "codex-agent-view-excluded-session";
5
5
  const LANGUAGE_KEY = "codex-agent-view-language";
6
6
  const SUPPORTED_LANGUAGES = new Set(["en", "ko", "es"]);
7
- const KNOWN_STATUSES = new Set(["running", "waiting", "completed", "unknown"]);
7
+ const KNOWN_STATUSES = new Set([
8
+ "running",
9
+ "waiting",
10
+ "completed",
11
+ "completion_not_observed",
12
+ "stale",
13
+ "interrupted",
14
+ "unknown",
15
+ ]);
8
16
  const VIEWER_TOKEN_PATTERN = /^[A-Za-z0-9_-]{43}$/;
9
17
  const CANONICAL_SESSION_ID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
10
18
 
11
19
  const MESSAGES = Object.freeze({
12
20
  en: Object.freeze({
13
- metaDescription: "Read-only local status for Codex tasks and subagents.",
21
+ metaDescription: "A clear, live view of Codex work and the agents moving it forward.",
14
22
  skipToContent: "Skip to content",
15
23
  brandHome: "Codex Agent View home",
16
- brandSubtitle: "Local read-only monitor",
24
+ brandSubtitle: "Live work overview",
17
25
  languageLabel: "Language",
18
26
  connectionConnecting: "Connecting to local status",
19
27
  connectionConnected: "Local monitor connected",
20
28
  connectionRetrying: "Disconnected · retrying",
21
29
  authenticationRequired: "Live view authentication required",
22
- heroEyebrow: "LOCAL · READ ONLY",
30
+ heroEyebrow: "LIVE CODEX WORK",
23
31
  heroTitle: "See active work at a glance",
24
- heroCopy: "Keep using the official Codex app while viewing the current status of parent tasks and subagents locally.",
32
+ heroCopy: "See what Codex is working on, which agents are involved, and how each part is progressing—all in one place.",
25
33
  freshnessAria: "Refresh information",
26
34
  lastUpdatedLabel: "Last updated",
27
35
  notYet: "Not yet",
28
36
  refreshIntervalLabel: "Refresh interval",
29
37
  twoSeconds: "2 seconds",
30
38
  metricsAria: "Task status summary",
31
- parentTasks: "Parent tasks",
39
+ parentTasks: "Work items",
32
40
  currentlyObserved: "Currently observed",
33
- runningAgents: "Running subagents",
41
+ runningAgents: "Active agents",
34
42
  workingNow: "Working now",
35
43
  waitingStatus: "Waiting",
36
44
  waitingExplanation: "Waiting for input or the next step",
37
- completedAgents: "Completed subagents",
45
+ completedAgents: "Completed agents",
38
46
  currentView: "In the current view",
39
47
  liveWork: "LIVE WORK",
40
- sessionsHeading: "Parent tasks and subagents",
48
+ sessionsHeading: "Work and participating agents",
41
49
  loadingState: "Loading status.",
42
- toolbarAria: "Filter automatically observed parent tasks and subagents",
50
+ toolbarAria: "Filter automatically observed work and participating agents",
43
51
  searchLabel: "Filter list (optional)",
44
- searchPlaceholder: "Find a parent task or subagent",
52
+ searchPlaceholder: "Find work or an agent",
45
53
  statusFilterLabel: "Status filter (optional)",
46
54
  statusAll: "All statuses",
47
55
  statusRunning: "Running",
48
56
  statusWaiting: "Waiting",
49
57
  statusCompleted: "Completed",
58
+ statusCompletionNotObserved: "End not confirmed",
59
+ statusStale: "Stale · end not confirmed",
60
+ statusInterrupted: "Interrupted",
50
61
  statusUnknown: "Unknown",
62
+ completionNotObservedExplanation: "No end signal was received for this item, so completion cannot be confirmed.",
63
+ staleExplanation: "This status is out of date and no end signal was received. Completion cannot be confirmed.",
64
+ interruptedExplanation: "This activity was still open when the work ended; its own completion signal was not observed.",
51
65
  connectingCopy: "Connecting to the Codex app's local status.",
52
- sessionListAria: "Codex parent task list",
53
- privacyPrompt: "This view does not display user requests or tool inputs.",
66
+ sessionListAria: "Codex work list",
67
+ privacyPrompt: "This view shows only a shortened request summary; it never displays the full request or tool inputs.",
54
68
  privacyLocal: "Data is read only from the local monitor on this device.",
55
69
  timeUnknown: "Time unavailable",
56
70
  startedUnknown: "Start time unavailable",
57
71
  noReceivedActivity: "No activity received",
58
- parentTask: "PARENT TASK",
72
+ parentTask: "WORK",
59
73
  projectUnknown: "Project unavailable",
74
+ taskSummary: "Request",
75
+ taskSummaryUnavailable: "A short request summary is not available yet.",
60
76
  recentActivity: "Recent activity",
61
77
  recent: "Recent",
62
- subagentsCount: "Subagents · {count}",
63
- subagentName: "Subagent {ordinal}",
78
+ subagentsCount: "Participating agents · {count}",
79
+ subagentName: "Agent {ordinal}",
64
80
  agentProfile: "Role/profile · {profile}",
65
- agentProfileNote: "Verified hooks do not expose assignment descriptions. Role/profile is shown when available.",
66
- noSubagents: "No subagents have been observed for this parent task.",
81
+ agentProfileNote: "Codex currently provides each agent's role, but not its full assignment description.",
82
+ noSubagents: "No participating agents have been observed for this work item.",
67
83
  noRecentActivity: "No recent activity to display.",
68
84
  technicalInfo: "Technical information",
69
- sessionId: "Session ID",
70
85
  agentId: "Agent ID",
71
86
  rawProfile: "Raw role/profile",
72
87
  rawEvent: "Raw event",
73
88
  rawTool: "Raw tool",
74
- retry: "Reconnect",
89
+ retry: "Retry connection",
90
+ retryAuthentication: "Try this tab again",
91
+ checkAuthentication: "Check authentication again",
92
+ recoveryTitle: "Open a newly authenticated view",
93
+ recoveryStep: "In the Codex app, select @codex-agent-view in the composer, then choose the actual $show-agents skill from the skill picker.",
94
+ recoveryNote: "The skill opens a new live view with fresh authentication. No terminal command or external browser is needed.",
75
95
  resultsFiltered: "Showing {visible} of {total}",
76
- resultsTotal: "{count} parent tasks",
96
+ resultsTotal: "{count} work items",
77
97
  searchEmptyTitle: "No matching results.",
78
98
  searchEmptyCopy: "Try changing the search term or status filter.",
79
- emptyWithDiagnosticsTitle: "No parent tasks can be displayed.",
80
- emptyWithDiagnosticsCopy: "The local monitor received {count} activity records but could not apply them to displayable parent tasks.",
99
+ emptyWithDiagnosticsTitle: "No work can be displayed.",
100
+ emptyWithDiagnosticsCopy: "The local monitor received {count} activity records but could not apply them to displayable work items.",
81
101
  emptyTitle: "No task activity has been received in this observation window.",
82
- emptyCopy: "The local monitor is connected. This result alone does not mean that Codex has no running parent tasks or subagents.",
102
+ emptyCopy: "The local monitor is connected. This result alone does not mean that Codex has no active work or participating agents.",
83
103
  emptyGuidanceTitle: "If work does not appear",
84
104
  automaticTracking: "You do not need to enter or register task IDs. Activity from trusted hooks is added automatically.",
85
105
  emptyStep1: "After installing the plugin, fully restart the official Codex app.",
86
106
  emptyStep2: "In a new task, review and explicitly trust the Codex Agent View hook command.",
87
- emptyStep3: "After trusting it, start a new task and run subagents. New activity is added automatically.",
107
+ emptyStep3: "After trusting it, start new work and run agents. New activity is added automatically.",
88
108
  observationBoundary: "Observation starts with the first trusted hook event. Earlier activity and activity missed while local collection was stopped cannot be replayed; restarting collection opens a new observation window.",
89
109
  diagnosticsCount: "Validation information · {count}",
90
110
  diagnosticOccurrences: "{count} occurrences",
@@ -92,8 +112,8 @@ const MESSAGES = Object.freeze({
92
112
  authTitle: "This live view cannot be authenticated.",
93
113
  retryWithState: "Reconnecting automatically every 2 seconds while keeping the last good state visible.",
94
114
  retryWithoutState: "Reconnecting automatically every 2 seconds. You can leave this view open in the Codex app.",
95
- missingToken: "This tab has no access token. Ask Codex Agent View to open the live view again in the Codex app.",
96
- expiredToken: "This live view credential is no longer valid. Ask Codex Agent View to open the live view again in the Codex app.",
115
+ missingToken: "This tab does not have the authentication needed to display live work.",
116
+ expiredToken: "This tab's live-view authentication was rejected or is no longer valid.",
97
117
  requestFailed: "Status request failed ({status})",
98
118
  unknownConnectionError: "An unknown connection error occurred.",
99
119
  offline: "This device is offline.",
@@ -107,25 +127,25 @@ const MESSAGES = Object.freeze({
107
127
  nameUnknown: "Unknown name",
108
128
  activityUnknown: "Unknown",
109
129
  approvalRequest: "{tool} approval requested",
110
- agentStarted: "Subagent {ordinal} started",
111
- agentStopped: "Subagent {ordinal} completed",
130
+ agentStarted: "Agent {ordinal} started",
131
+ agentStopped: "Agent {ordinal} completed",
112
132
  activitySessionStarted: "Observation started",
113
133
  activitySessionEnded: "Observation ended",
114
- activityTurnStarted: "Parent task started",
115
- activityTurnStopped: "Parent task response completed",
116
- activitySubagentStarted: "Subagent started",
117
- activitySubagentStopped: "Subagent completed",
134
+ activityTurnStarted: "Work started",
135
+ activityTurnStopped: "Work response completed",
136
+ activitySubagentStarted: "Agent started",
137
+ activitySubagentStopped: "Agent completed",
118
138
  activityToolStarted: "Tool activity",
119
139
  activityToolCompleted: "Tool activity",
120
140
  activityPermissionRequested: "User approval requested",
121
141
  toolApplyPatch: "File edit",
122
142
  toolBash: "Terminal activity",
123
- toolFollowup: "Subagent follow-up requested",
124
- toolInterrupt: "Subagent interruption requested",
125
- toolList: "Subagent status checked",
126
- toolMessage: "Message sent to subagent",
127
- toolSpawn: "Subagent started",
128
- toolWaitAgent: "Waiting for subagent",
143
+ toolFollowup: "Agent follow-up requested",
144
+ toolInterrupt: "Agent interruption requested",
145
+ toolList: "Agent status checked",
146
+ toolMessage: "Message sent to agent",
147
+ toolSpawn: "Agent started",
148
+ toolWaitAgent: "Waiting for agent",
129
149
  toolExec: "Terminal activity",
130
150
  toolUserInput: "User input requested",
131
151
  toolWait: "Waiting for completion",
@@ -137,25 +157,25 @@ const MESSAGES = Object.freeze({
137
157
  roleUnknown: "Not reported",
138
158
  }),
139
159
  ko: Object.freeze({
140
- metaDescription: "공식 Codex 앱의 부모 작업과 작업 에이전트 상태를 로컬에서 읽기 전용으로 확인합니다.",
160
+ metaDescription: "Codex 수행 중인 작업과 참여 에이전트의 진행 상황을 한눈에 확인합니다.",
141
161
  skipToContent: "본문으로 건너뛰기",
142
162
  brandHome: "Codex Agent View 홈",
143
- brandSubtitle: "로컬 읽기 전용 모니터",
163
+ brandSubtitle: "실시간 작업 현황",
144
164
  languageLabel: "언어",
145
165
  connectionConnecting: "로컬 상태 연결 중",
146
166
  connectionConnected: "로컬 모니터 연결됨",
147
167
  connectionRetrying: "연결 끊김 · 재시도 중",
148
168
  authenticationRequired: "실시간 화면 인증 필요",
149
- heroEyebrow: "로컬 · 읽기 전용",
169
+ heroEyebrow: "CODEX 작업 현황",
150
170
  heroTitle: "작업 흐름을 한눈에",
151
- heroCopy: "공식 Codex 앱은 그대로 두고, 부모 작업과 작업 에이전트의 현재 상태만 로컬에서 확인합니다.",
171
+ heroCopy: "Codex 어떤 요청을 처리하고 있는지, 어떤 에이전트가 참여하는지, 단계가 어디까지 왔는지 한 화면에서 확인하세요.",
152
172
  freshnessAria: "상태 갱신 정보",
153
173
  lastUpdatedLabel: "마지막 갱신",
154
174
  notYet: "아직 없음",
155
175
  refreshIntervalLabel: "갱신 주기",
156
176
  twoSeconds: "2초",
157
177
  metricsAria: "작업 상태 요약",
158
- parentTasks: "부모 작업",
178
+ parentTasks: "작업",
159
179
  currentlyObserved: "현재 관찰 중",
160
180
  runningAgents: "실행 중 에이전트",
161
181
  workingNow: "작업 수행 중",
@@ -164,54 +184,66 @@ const MESSAGES = Object.freeze({
164
184
  completedAgents: "완료 에이전트",
165
185
  currentView: "현재 화면 기준",
166
186
  liveWork: "실시간 작업",
167
- sessionsHeading: "부모 작업과 작업 에이전트",
187
+ sessionsHeading: "작업과 참여 에이전트",
168
188
  loadingState: "상태를 불러오는 중입니다.",
169
- toolbarAria: "자동 수신된 부모 작업과 작업 에이전트 목록 필터",
189
+ toolbarAria: "자동 수신된 작업과 참여 에이전트 목록 필터",
170
190
  searchLabel: "목록 필터 (선택)",
171
- searchPlaceholder: "부모 작업·작업 에이전트 목록에서 찾기",
191
+ searchPlaceholder: "작업 또는 에이전트 찾기",
172
192
  statusFilterLabel: "상태 필터 (선택)",
173
193
  statusAll: "모든 상태",
174
194
  statusRunning: "실행 중",
175
195
  statusWaiting: "대기",
176
196
  statusCompleted: "완료",
197
+ statusCompletionNotObserved: "종료 확인 안 됨",
198
+ statusStale: "오래된 상태 · 종료 확인 안 됨",
199
+ statusInterrupted: "중단됨",
177
200
  statusUnknown: "알 수 없음",
201
+ completionNotObservedExplanation: "이 항목의 종료 신호를 받지 못해 완료 여부를 확정할 수 없습니다.",
202
+ staleExplanation: "상태 정보가 오래되었고 종료 신호를 받지 못했습니다. 완료 여부를 확정할 수 없습니다.",
203
+ interruptedExplanation: "전체 작업이 끝날 때 이 활동이 열린 상태였습니다. 이 활동 자체의 완료 신호는 확인되지 않았습니다.",
178
204
  connectingCopy: "Codex 앱의 로컬 상태에 연결하고 있습니다.",
179
- sessionListAria: "Codex 부모 작업 목록",
180
- privacyPrompt: "이 화면은 사용자 요청 내용과 도구 입력 내용을 표시하지 않습니다.",
205
+ sessionListAria: "Codex 작업 목록",
206
+ privacyPrompt: "이 화면은 짧게 줄인 요청 요약만 표시하며, 전체 요청이나 도구 입력은 표시하지 않습니다.",
181
207
  privacyLocal: "데이터는 이 기기의 로컬 모니터에서만 읽습니다.",
182
208
  timeUnknown: "시간 정보 없음",
183
209
  startedUnknown: "시작 시간 없음",
184
210
  noReceivedActivity: "수신된 활동 없음",
185
- parentTask: "부모 작업",
211
+ parentTask: "작업",
186
212
  projectUnknown: "프로젝트 정보 없음",
213
+ taskSummary: "요청 내용",
214
+ taskSummaryUnavailable: "요청 내용을 요약할 수 있는 정보가 아직 없습니다.",
187
215
  recentActivity: "최근 활동",
188
216
  recent: "최근",
189
- subagentsCount: "작업 에이전트 · {count}",
190
- subagentName: "작업 에이전트 {ordinal}",
217
+ subagentsCount: "참여 에이전트 · {count}",
218
+ subagentName: "에이전트 {ordinal}",
191
219
  agentProfile: "역할/프로필 · {profile}",
192
- agentProfileNote: "검증된 hook은 할당 작업 설명을 제공하지 않습니다. 확인 가능한 역할/프로필만 표시합니다.",
193
- noSubagents: "이 부모 작업에서 관찰된 작업 에이전트가 없습니다.",
220
+ agentProfileNote: "Codex는 현재 에이전트의 역할을 제공하지만, 구체적인 할당 내용 전체는 제공하지 않습니다.",
221
+ noSubagents: "이 작업에 참여한 에이전트가 아직 관찰되지 않았습니다.",
194
222
  noRecentActivity: "표시할 최근 활동이 없습니다.",
195
223
  technicalInfo: "기술 정보",
196
- sessionId: "세션 ID",
197
224
  agentId: "에이전트 ID",
198
225
  rawProfile: "원본 역할/프로필",
199
226
  rawEvent: "원본 이벤트",
200
227
  rawTool: "원본 도구",
201
- retry: "다시 연결",
228
+ retry: "연결 다시 시도",
229
+ retryAuthentication: "이 탭에서 다시 시도",
230
+ checkAuthentication: "인증 정보 다시 확인",
231
+ recoveryTitle: "새 인증 화면 열기",
232
+ recoveryStep: "Codex 앱 입력창에서 @codex-agent-view를 선택한 다음, 스킬 선택기에서 실제 $show-agents 스킬을 선택하세요.",
233
+ recoveryNote: "새 인증이 적용된 실시간 화면이 열립니다. 터미널 명령이나 외부 브라우저는 필요하지 않습니다.",
202
234
  resultsFiltered: "전체 {total}개 중 {visible}개 표시",
203
- resultsTotal: "{count}개 부모 작업",
235
+ resultsTotal: "작업 {count}개",
204
236
  searchEmptyTitle: "검색 결과가 없습니다.",
205
237
  searchEmptyCopy: "검색어나 상태 필터를 바꿔 보세요.",
206
- emptyWithDiagnosticsTitle: "표시 가능한 부모 작업이 없습니다.",
207
- emptyWithDiagnosticsCopy: "로컬 모니터가 활동 정보 {count}건을 받았지만 표시 가능한 부모 작업으로 적용하지 못했습니다.",
238
+ emptyWithDiagnosticsTitle: "표시 가능한 작업이 없습니다.",
239
+ emptyWithDiagnosticsCopy: "로컬 모니터가 활동 정보 {count}건을 받았지만 표시 가능한 작업으로 적용하지 못했습니다.",
208
240
  emptyTitle: "이 관찰 화면에서 수신된 작업 활동이 없습니다.",
209
- emptyCopy: "로컬 모니터 연결은 정상입니다. 이 결과만으로 Codex에 실행 중인 부모 작업이나 작업 에이전트가 없다고 판단할 수 없습니다.",
241
+ emptyCopy: "로컬 모니터 연결은 정상입니다. 이 결과만으로 Codex에 진행 중인 작업이나 참여 에이전트가 없다고 판단할 수 없습니다.",
210
242
  emptyGuidanceTitle: "표시되지 않을 때 확인 순서",
211
243
  automaticTracking: "작업 ID를 입력하거나 작업별로 등록할 필요가 없습니다. 신뢰한 hook의 작업 활동이 이 목록에 자동으로 추가됩니다.",
212
244
  emptyStep1: "플러그인을 설치한 뒤 공식 Codex 앱을 완전히 재시작했는지 확인합니다.",
213
245
  emptyStep2: "새 작업에서 표시되는 Codex Agent View hook 명령을 검토하고 직접 신뢰합니다.",
214
- emptyStep3: "신뢰 설정 후 새 작업을 시작해 작업 에이전트를 실행합니다. 새 활동은 이 목록에 자동으로 추가됩니다.",
246
+ emptyStep3: "신뢰 설정 후 새 작업을 시작해 에이전트를 실행합니다. 새 활동은 이 목록에 자동으로 추가됩니다.",
215
247
  observationBoundary: "관찰 화면은 첫 번째로 신뢰한 hook을 받은 시점부터 시작합니다. 그 전에 이미 지나간 활동과 로컬 상태 수집이 중단된 동안의 활동은 재생되지 않으며, 수집이 다시 시작되면 새 관찰 화면이 열립니다.",
216
248
  diagnosticsCount: "검증 정보 · {count}건",
217
249
  diagnosticOccurrences: "{count}건",
@@ -219,8 +251,8 @@ const MESSAGES = Object.freeze({
219
251
  authTitle: "이 실시간 화면을 인증할 수 없습니다.",
220
252
  retryWithState: "2초마다 자동으로 다시 연결합니다. 마지막 정상 상태를 계속 표시합니다.",
221
253
  retryWithoutState: "2초마다 자동으로 다시 연결합니다. Codex 앱에서 이 화면을 그대로 두어도 됩니다.",
222
- missingToken: "이 탭에는 접근 토큰이 없습니다. Codex 앱에서 Codex Agent View의 실시간 화면 열기를 다시 요청하세요.",
223
- expiredToken: "이 실시간 화면의 인증이 더 이상 유효하지 않습니다. Codex 앱에서 Codex Agent View의 실시간 화면 열기를 다시 요청하세요.",
254
+ missingToken: "이 탭에는 실시간 작업을 표시하는 필요한 인증 정보가 없습니다.",
255
+ expiredToken: "이 탭의 실시간 화면 인증이 거부되었거나 더 이상 유효하지 않습니다.",
224
256
  requestFailed: "상태 요청 실패 ({status})",
225
257
  unknownConnectionError: "알 수 없는 연결 오류가 발생했습니다.",
226
258
  offline: "이 기기가 오프라인입니다.",
@@ -234,14 +266,14 @@ const MESSAGES = Object.freeze({
234
266
  nameUnknown: "이름 미상",
235
267
  activityUnknown: "알 수 없음",
236
268
  approvalRequest: "{tool} 승인 요청",
237
- agentStarted: "작업 에이전트 {ordinal} 시작",
238
- agentStopped: "작업 에이전트 {ordinal} 완료",
269
+ agentStarted: "에이전트 {ordinal} 시작",
270
+ agentStopped: "에이전트 {ordinal} 완료",
239
271
  activitySessionStarted: "관찰 시작",
240
272
  activitySessionEnded: "관찰 종료",
241
- activityTurnStarted: "부모 작업 시작",
242
- activityTurnStopped: "부모 작업 응답 완료",
243
- activitySubagentStarted: "작업 에이전트 시작",
244
- activitySubagentStopped: "작업 에이전트 완료",
273
+ activityTurnStarted: "작업 시작",
274
+ activityTurnStopped: "작업 응답 완료",
275
+ activitySubagentStarted: "에이전트 시작",
276
+ activitySubagentStopped: "에이전트 완료",
245
277
  activityToolStarted: "도구 작업",
246
278
  activityToolCompleted: "도구 작업",
247
279
  activityPermissionRequested: "사용자 승인 요청",
@@ -251,7 +283,7 @@ const MESSAGES = Object.freeze({
251
283
  toolInterrupt: "에이전트 작업 중단 요청",
252
284
  toolList: "에이전트 상태 확인",
253
285
  toolMessage: "에이전트에게 메시지 전달",
254
- toolSpawn: "작업 에이전트 시작",
286
+ toolSpawn: "에이전트 시작",
255
287
  toolWaitAgent: "에이전트 응답 대기",
256
288
  toolExec: "터미널 작업",
257
289
  toolUserInput: "사용자 입력 요청",
@@ -264,81 +296,93 @@ const MESSAGES = Object.freeze({
264
296
  roleUnknown: "보고되지 않음",
265
297
  }),
266
298
  es: Object.freeze({
267
- metaDescription: "Estado local y de solo lectura de tareas y subagentes de Codex.",
299
+ metaDescription: "Una vista clara del trabajo de Codex y de los agentes que lo hacen avanzar.",
268
300
  skipToContent: "Saltar al contenido",
269
301
  brandHome: "Inicio de Codex Agent View",
270
- brandSubtitle: "Monitor local de solo lectura",
302
+ brandSubtitle: "Resumen del trabajo en vivo",
271
303
  languageLabel: "Idioma",
272
304
  connectionConnecting: "Conectando al estado local",
273
305
  connectionConnected: "Monitor local conectado",
274
306
  connectionRetrying: "Desconectado · reintentando",
275
307
  authenticationRequired: "Se requiere autenticar la vista",
276
- heroEyebrow: "LOCAL · SOLO LECTURA",
308
+ heroEyebrow: "TRABAJO ACTIVO EN CODEX",
277
309
  heroTitle: "Observa el trabajo activo de un vistazo",
278
- heroCopy: "Sigue usando la aplicación oficial de Codex mientras consultas localmente el estado de las tareas principales y los subagentes.",
310
+ heroCopy: "Consulta qué está haciendo Codex, qué agentes participan y cómo avanza cada parte, todo en un solo lugar.",
279
311
  freshnessAria: "Información de actualización",
280
312
  lastUpdatedLabel: "Última actualización",
281
313
  notYet: "Aún no",
282
314
  refreshIntervalLabel: "Intervalo de actualización",
283
315
  twoSeconds: "2 segundos",
284
316
  metricsAria: "Resumen del estado de las tareas",
285
- parentTasks: "Tareas principales",
317
+ parentTasks: "Trabajos",
286
318
  currentlyObserved: "En observación",
287
- runningAgents: "Subagentes activos",
319
+ runningAgents: "Agentes activos",
288
320
  workingNow: "Trabajando ahora",
289
321
  waitingStatus: "En espera",
290
322
  waitingExplanation: "Esperando una respuesta o el siguiente paso",
291
- completedAgents: "Subagentes completados",
323
+ completedAgents: "Agentes que terminaron",
292
324
  currentView: "En la vista actual",
293
325
  liveWork: "TRABAJO EN VIVO",
294
- sessionsHeading: "Tareas principales y subagentes",
326
+ sessionsHeading: "Trabajos y agentes participantes",
295
327
  loadingState: "Cargando el estado.",
296
- toolbarAria: "Filtrar tareas principales y subagentes observados automáticamente",
328
+ toolbarAria: "Filtrar trabajos y agentes participantes observados automáticamente",
297
329
  searchLabel: "Filtrar lista (opcional)",
298
- searchPlaceholder: "Buscar una tarea principal o un subagente",
330
+ searchPlaceholder: "Buscar un trabajo o agente",
299
331
  statusFilterLabel: "Filtrar por estado (opcional)",
300
332
  statusAll: "Todos los estados",
301
333
  statusRunning: "En ejecución",
302
334
  statusWaiting: "En espera",
303
335
  statusCompleted: "Completado",
336
+ statusCompletionNotObserved: "Fin no confirmado",
337
+ statusStale: "Estado desactualizado · fin no confirmado",
338
+ statusInterrupted: "Interrumpido",
304
339
  statusUnknown: "Desconocido",
340
+ completionNotObservedExplanation: "No se recibió una señal de fin para este elemento, por lo que no se puede confirmar que haya terminado.",
341
+ staleExplanation: "El estado está desactualizado y no se recibió una señal de fin. No se puede confirmar que haya terminado.",
342
+ interruptedExplanation: "Esta actividad seguía abierta cuando terminó el trabajo; no se observó su propia señal de finalización.",
305
343
  connectingCopy: "Conectando al estado local de la aplicación Codex.",
306
- sessionListAria: "Lista de tareas principales de Codex",
307
- privacyPrompt: "Esta vista no muestra solicitudes del usuario ni entradas de herramientas.",
344
+ sessionListAria: "Lista de trabajos de Codex",
345
+ privacyPrompt: "Esta vista solo muestra un resumen abreviado de la solicitud; nunca muestra la solicitud completa ni las entradas de herramientas.",
308
346
  privacyLocal: "Los datos se leen únicamente del monitor local de este dispositivo.",
309
347
  timeUnknown: "Hora no disponible",
310
348
  startedUnknown: "Hora de inicio no disponible",
311
349
  noReceivedActivity: "No se recibió actividad",
312
- parentTask: "TAREA PRINCIPAL",
350
+ parentTask: "TRABAJO",
313
351
  projectUnknown: "Proyecto no disponible",
352
+ taskSummary: "Solicitud",
353
+ taskSummaryUnavailable: "Todavía no hay información para resumir esta solicitud.",
314
354
  recentActivity: "Actividad reciente",
315
355
  recent: "Reciente",
316
- subagentsCount: "Subagentes · {count}",
317
- subagentName: "Subagente {ordinal}",
356
+ subagentsCount: "Agentes participantes · {count}",
357
+ subagentName: "Agente {ordinal}",
318
358
  agentProfile: "Rol/perfil · {profile}",
319
- agentProfileNote: "Los hooks verificados no proporcionan descripciones de la tarea asignada. Se muestra el rol/perfil cuando está disponible.",
320
- noSubagents: "No se observaron subagentes para esta tarea principal.",
359
+ agentProfileNote: "Codex proporciona el rol de cada agente, pero no la descripción completa de su asignación.",
360
+ noSubagents: "Todavía no se observaron agentes participantes en este trabajo.",
321
361
  noRecentActivity: "No hay actividad reciente que mostrar.",
322
362
  technicalInfo: "Información técnica",
323
- sessionId: "ID de sesión",
324
363
  agentId: "ID del agente",
325
364
  rawProfile: "Rol/perfil original",
326
365
  rawEvent: "Evento original",
327
366
  rawTool: "Herramienta original",
328
- retry: "Reconectar",
367
+ retry: "Reintentar conexión",
368
+ retryAuthentication: "Reintentar en esta pestaña",
369
+ checkAuthentication: "Volver a comprobar la autenticación",
370
+ recoveryTitle: "Abrir una vista con autenticación nueva",
371
+ recoveryStep: "En el cuadro de texto de Codex, selecciona @codex-agent-view y luego elige la skill real $show-agents en el selector de skills.",
372
+ recoveryNote: "La skill abre una vista en vivo nueva con autenticación actualizada. No necesitas la terminal ni un navegador externo.",
329
373
  resultsFiltered: "Mostrando {visible} de {total}",
330
- resultsTotal: "{count} tareas principales",
374
+ resultsTotal: "{count} trabajos",
331
375
  searchEmptyTitle: "No hay resultados.",
332
376
  searchEmptyCopy: "Prueba otra búsqueda o filtro de estado.",
333
- emptyWithDiagnosticsTitle: "No hay tareas principales que mostrar.",
334
- emptyWithDiagnosticsCopy: "El monitor local recibió {count} registros de actividad, pero no pudo aplicarlos a tareas visibles.",
377
+ emptyWithDiagnosticsTitle: "No hay trabajos que mostrar.",
378
+ emptyWithDiagnosticsCopy: "El monitor local recibió {count} registros de actividad, pero no pudo aplicarlos a trabajos visibles.",
335
379
  emptyTitle: "No se recibió actividad en esta ventana de observación.",
336
- emptyCopy: "El monitor local está conectado. Este resultado no implica por sí solo que Codex no tenga tareas o subagentes activos.",
380
+ emptyCopy: "El monitor local está conectado. Este resultado no implica por sí solo que Codex no tenga trabajos o agentes activos.",
337
381
  emptyGuidanceTitle: "Si el trabajo no aparece",
338
382
  automaticTracking: "No es necesario introducir ni registrar IDs de tareas. La actividad de hooks confiables se añade automáticamente.",
339
383
  emptyStep1: "Tras instalar el plugin, reinicia por completo la aplicación oficial de Codex.",
340
384
  emptyStep2: "En una tarea nueva, revisa y autoriza explícitamente el comando hook de Codex Agent View.",
341
- emptyStep3: "Después, inicia una tarea nueva y ejecuta subagentes. La actividad se añadirá automáticamente.",
385
+ emptyStep3: "Después, inicia un trabajo nuevo y ejecuta agentes. La actividad se añadirá automáticamente.",
342
386
  observationBoundary: "La observación comienza con el primer evento de un hook autorizado. La actividad anterior o perdida mientras la recopilación local estuvo detenida no se puede reproducir; al reiniciarla se abre una ventana nueva.",
343
387
  diagnosticsCount: "Información de validación · {count}",
344
388
  diagnosticOccurrences: "{count} apariciones",
@@ -346,8 +390,8 @@ const MESSAGES = Object.freeze({
346
390
  authTitle: "No se puede autenticar esta vista en vivo.",
347
391
  retryWithState: "Se reconecta automáticamente cada 2 segundos y mantiene visible el último estado válido.",
348
392
  retryWithoutState: "Se reconecta automáticamente cada 2 segundos. Puedes dejar esta vista abierta en Codex.",
349
- missingToken: "Esta pestaña no tiene un token de acceso. Pide a Codex Agent View que vuelva a abrir la vista en Codex.",
350
- expiredToken: "La credencial de esta vista ya no es válida. Pide a Codex Agent View que vuelva a abrir la vista en Codex.",
393
+ missingToken: "Esta pestaña no tiene la autenticación necesaria para mostrar el trabajo en vivo.",
394
+ expiredToken: "La autenticación de esta pestaña fue rechazada o ya no es válida.",
351
395
  requestFailed: "Falló la solicitud de estado ({status})",
352
396
  unknownConnectionError: "Se produjo un error de conexión desconocido.",
353
397
  offline: "Este dispositivo está sin conexión.",
@@ -361,25 +405,25 @@ const MESSAGES = Object.freeze({
361
405
  nameUnknown: "Nombre desconocido",
362
406
  activityUnknown: "Desconocida",
363
407
  approvalRequest: "Se solicitó aprobación para {tool}",
364
- agentStarted: "Subagente {ordinal} iniciado",
365
- agentStopped: "Subagente {ordinal} completado",
408
+ agentStarted: "Agente {ordinal} iniciado",
409
+ agentStopped: "Agente {ordinal} completado",
366
410
  activitySessionStarted: "Observación iniciada",
367
411
  activitySessionEnded: "Observación finalizada",
368
- activityTurnStarted: "Tarea principal iniciada",
369
- activityTurnStopped: "Respuesta de la tarea completada",
370
- activitySubagentStarted: "Subagente iniciado",
371
- activitySubagentStopped: "Subagente completado",
412
+ activityTurnStarted: "Trabajo iniciado",
413
+ activityTurnStopped: "Respuesta del trabajo completada",
414
+ activitySubagentStarted: "Agente iniciado",
415
+ activitySubagentStopped: "Agente completado",
372
416
  activityToolStarted: "Actividad de herramienta",
373
417
  activityToolCompleted: "Actividad de herramienta",
374
418
  activityPermissionRequested: "Se solicitó aprobación",
375
419
  toolApplyPatch: "Edición de archivo",
376
420
  toolBash: "Actividad de terminal",
377
- toolFollowup: "Seguimiento del subagente solicitado",
378
- toolInterrupt: "Interrupción del subagente solicitada",
379
- toolList: "Estado de subagentes consultado",
380
- toolMessage: "Mensaje enviado al subagente",
381
- toolSpawn: "Subagente iniciado",
382
- toolWaitAgent: "Esperando al subagente",
421
+ toolFollowup: "Seguimiento del agente solicitado",
422
+ toolInterrupt: "Interrupción del agente solicitada",
423
+ toolList: "Estado de agentes consultado",
424
+ toolMessage: "Mensaje enviado al agente",
425
+ toolSpawn: "Agente iniciado",
426
+ toolWaitAgent: "Esperando al agente",
383
427
  toolExec: "Actividad de terminal",
384
428
  toolUserInput: "Se solicitó entrada del usuario",
385
429
  toolWait: "Esperando finalización",
@@ -396,14 +440,26 @@ const STATUS_KEYS = Object.freeze({
396
440
  running: "statusRunning",
397
441
  waiting: "statusWaiting",
398
442
  completed: "statusCompleted",
443
+ completion_not_observed: "statusCompletionNotObserved",
444
+ stale: "statusStale",
445
+ interrupted: "statusInterrupted",
399
446
  unknown: "statusUnknown",
400
447
  });
401
448
 
402
449
  const STATUS_ORDER = Object.freeze({
403
450
  running: 0,
404
451
  waiting: 1,
405
- unknown: 2,
406
- completed: 3,
452
+ completion_not_observed: 2,
453
+ stale: 2,
454
+ interrupted: 3,
455
+ unknown: 4,
456
+ completed: 5,
457
+ });
458
+
459
+ const STATUS_EXPLANATION_KEYS = Object.freeze({
460
+ completion_not_observed: "completionNotObservedExplanation",
461
+ stale: "staleExplanation",
462
+ interrupted: "interruptedExplanation",
407
463
  });
408
464
 
409
465
  const ACTIVITY_KEYS = Object.freeze({
@@ -522,7 +578,7 @@ function consumeLiveContext() {
522
578
  };
523
579
  }
524
580
 
525
- const { accessToken, excludedSessionId } = consumeLiveContext();
581
+ let { accessToken, excludedSessionId } = consumeLiveContext();
526
582
 
527
583
  const elements = Object.freeze({
528
584
  connectionStatus: document.querySelector("#connection-status"),
@@ -675,6 +731,9 @@ function normalizeCoreStatus(value) {
675
731
  ) {
676
732
  return "completed";
677
733
  }
734
+ if (value === "completion_not_observed" || value === "stale" || value === "interrupted") {
735
+ return value;
736
+ }
678
737
  return normalizeStatus(value);
679
738
  }
680
739
 
@@ -765,13 +824,13 @@ function normalizeDiagnostic(value) {
765
824
  }
766
825
 
767
826
  function deriveSessionStatus(session, agents, recentActivities) {
768
- if (session.permission?.status === "waiting_for_user") {
769
- return "waiting";
770
- }
771
827
  const reportedStatus = normalizeCoreStatus(session.status);
772
- if (reportedStatus === "running" || reportedStatus === "completed") {
828
+ if (reportedStatus !== "unknown") {
773
829
  return reportedStatus;
774
830
  }
831
+ if (session.permission?.status === "waiting_for_user") {
832
+ return "waiting";
833
+ }
775
834
  if (
776
835
  agents.some((agent) => agent.status === "running") ||
777
836
  recentActivities[0]?.status === "running"
@@ -801,6 +860,7 @@ function normalizeSession(value, index) {
801
860
  return {
802
861
  sessionId: safeString(session.session_id, `unknown-session-${index + 1}`),
803
862
  workspaceLabel: safeString(session.workspace_label, ""),
863
+ taskSummary: safeString(session.task_summary, ""),
804
864
  status: deriveSessionStatus(session, agents, recentActivities),
805
865
  lastActivityAtMs: safeTimestamp(session.last_seen_at_ms),
806
866
  agents,
@@ -905,12 +965,24 @@ function createStatusBadge(status) {
905
965
  dot.setAttribute("aria-hidden", "true");
906
966
 
907
967
  const label = document.createElement("span");
908
- label.textContent = t(STATUS_KEYS[status]);
968
+ label.textContent = t(STATUS_KEYS[status] ?? "statusUnknown");
909
969
 
910
970
  badge.append(dot, label);
911
971
  return badge;
912
972
  }
913
973
 
974
+ function createStatusExplanation(status) {
975
+ const messageKey = STATUS_EXPLANATION_KEYS[status];
976
+ if (!messageKey) {
977
+ return null;
978
+ }
979
+
980
+ const explanation = document.createElement("p");
981
+ explanation.className = "status-explanation";
982
+ explanation.textContent = t(messageKey);
983
+ return explanation;
984
+ }
985
+
914
986
  function createTime(timestampMs, prefix) {
915
987
  const wrapper = document.createElement("span");
916
988
  wrapper.className = "time-label";
@@ -987,10 +1059,16 @@ function createAgentItem(agent) {
987
1059
  document.createTextNode(` · ${formatDuration(agent.startedAtMs, agent.stoppedAtMs)}`),
988
1060
  );
989
1061
 
1062
+ const statusExplanation = createStatusExplanation(agent.status);
1063
+
990
1064
  const technicalRows = [[t("agentId"), agent.agentId]];
991
1065
  technicalRows.push([t("rawProfile"), agent.agentType]);
992
1066
 
993
- item.append(heading, metadata, createTechnicalInfo(technicalRows));
1067
+ item.append(heading, metadata);
1068
+ if (statusExplanation) {
1069
+ item.append(statusExplanation);
1070
+ }
1071
+ item.append(createTechnicalInfo(technicalRows));
994
1072
  return item;
995
1073
  }
996
1074
 
@@ -1047,11 +1125,14 @@ function createSessionCard(session) {
1047
1125
  eyebrow.textContent = t("parentTask");
1048
1126
  const title = document.createElement("h3");
1049
1127
  title.textContent = session.workspaceLabel || t("projectUnknown");
1050
- identity.append(
1051
- eyebrow,
1052
- title,
1053
- createTechnicalInfo([[t("sessionId"), session.sessionId]]),
1054
- );
1128
+ const taskSummary = document.createElement("p");
1129
+ taskSummary.className = "task-summary";
1130
+ const taskSummaryLabel = document.createElement("strong");
1131
+ taskSummaryLabel.textContent = `${t("taskSummary")} · `;
1132
+ const taskSummaryCopy = document.createElement("span");
1133
+ taskSummaryCopy.textContent = session.taskSummary || t("taskSummaryUnavailable");
1134
+ taskSummary.append(taskSummaryLabel, taskSummaryCopy);
1135
+ identity.append(eyebrow, title, taskSummary);
1055
1136
 
1056
1137
  const sessionState = document.createElement("div");
1057
1138
  sessionState.className = "session-state";
@@ -1059,6 +1140,10 @@ function createSessionCard(session) {
1059
1140
  createStatusBadge(session.status),
1060
1141
  createTime(session.lastActivityAtMs, t("recentActivity")),
1061
1142
  );
1143
+ const statusExplanation = createStatusExplanation(session.status);
1144
+ if (statusExplanation) {
1145
+ sessionState.append(statusExplanation);
1146
+ }
1062
1147
 
1063
1148
  cardHeader.append(identity, sessionState);
1064
1149
 
@@ -1116,6 +1201,7 @@ function sessionMatchesQuery(session, query) {
1116
1201
  const searchableValues = [
1117
1202
  session.sessionId,
1118
1203
  session.workspaceLabel,
1204
+ session.taskSummary,
1119
1205
  session.status,
1120
1206
  ...session.agents.flatMap((agent) => [
1121
1207
  agent.agentId,
@@ -1133,10 +1219,15 @@ function sessionMatchesQuery(session, query) {
1133
1219
  }
1134
1220
 
1135
1221
  function sessionMatchesStatus(session, status) {
1222
+ const matchesStatus = (candidate) => (
1223
+ candidate === status ||
1224
+ (status === "completion_not_observed" && candidate === "stale")
1225
+ );
1136
1226
  return (
1137
1227
  status === "all" ||
1138
- session.status === status ||
1139
- session.agents.some((agent) => agent.status === status)
1228
+ matchesStatus(session.status) ||
1229
+ session.agents.some((agent) => matchesStatus(agent.status)) ||
1230
+ session.recentActivities.some((activity) => matchesStatus(activity.status))
1140
1231
  );
1141
1232
  }
1142
1233
 
@@ -1171,7 +1262,7 @@ function renderMetrics() {
1171
1262
  : formatDateTime(viewState.updatedAtMs);
1172
1263
  }
1173
1264
 
1174
- function setStateMessage(kind, title, description, includeRetry = false) {
1265
+ function setStateMessage(kind, title, description, retryMode = "") {
1175
1266
  elements.stateMessage.className = `state-message state-${kind}`;
1176
1267
  elements.stateMessage.replaceChildren();
1177
1268
 
@@ -1181,16 +1272,61 @@ function setStateMessage(kind, title, description, includeRetry = false) {
1181
1272
  copy.textContent = description;
1182
1273
  elements.stateMessage.append(heading, copy);
1183
1274
 
1184
- if (includeRetry) {
1275
+ if (retryMode === "authentication") {
1276
+ const recovery = document.createElement("div");
1277
+ recovery.className = "recovery-guidance";
1278
+
1279
+ const recoveryTitle = document.createElement("strong");
1280
+ recoveryTitle.textContent = t("recoveryTitle");
1281
+ const recoveryStep = document.createElement("p");
1282
+ recoveryStep.textContent = t("recoveryStep");
1283
+ const recoveryNote = document.createElement("p");
1284
+ recoveryNote.className = "recovery-note";
1285
+ recoveryNote.textContent = t("recoveryNote");
1286
+ recovery.append(recoveryTitle, recoveryStep, recoveryNote);
1287
+ elements.stateMessage.append(recovery);
1288
+ }
1289
+
1290
+ if (retryMode) {
1185
1291
  const retry = document.createElement("button");
1186
1292
  retry.type = "button";
1187
1293
  retry.className = "retry-button";
1188
- retry.textContent = t("retry");
1189
- retry.addEventListener("click", refreshState);
1294
+ retry.textContent = retryMode === "authentication"
1295
+ ? (accessToken ? t("retryAuthentication") : t("checkAuthentication"))
1296
+ : t("retry");
1297
+ retry.addEventListener(
1298
+ "click",
1299
+ retryMode === "authentication" ? retryAuthentication : refreshState,
1300
+ );
1190
1301
  elements.stateMessage.append(retry);
1191
1302
  }
1192
1303
  }
1193
1304
 
1305
+ function retryAuthentication() {
1306
+ const refreshedContext = consumeLiveContext();
1307
+ accessToken = refreshedContext.accessToken;
1308
+ excludedSessionId = refreshedContext.excludedSessionId;
1309
+
1310
+ if (!accessToken) {
1311
+ viewState.hasLoaded = true;
1312
+ viewState.canRetry = false;
1313
+ viewState.authenticationFailed = true;
1314
+ viewState.errorKey = "missingToken";
1315
+ viewState.errorMessage = t(viewState.errorKey);
1316
+ setConnectionStatus("error", t("authenticationRequired"));
1317
+ render();
1318
+ return;
1319
+ }
1320
+
1321
+ viewState.authenticationFailed = false;
1322
+ viewState.canRetry = true;
1323
+ viewState.errorKey = "";
1324
+ viewState.errorMessage = "";
1325
+ setConnectionStatus("connecting");
1326
+ render();
1327
+ void refreshState();
1328
+ }
1329
+
1194
1330
  function setEmptyObservationMessage() {
1195
1331
  elements.stateMessage.className = "state-message state-empty state-empty-observation";
1196
1332
  elements.stateMessage.replaceChildren();
@@ -1290,7 +1426,7 @@ function renderSessions() {
1290
1426
  ? t("disconnectedTitle")
1291
1427
  : t("authTitle"),
1292
1428
  description,
1293
- viewState.canRetry,
1429
+ viewState.canRetry ? "connection" : "authentication",
1294
1430
  );
1295
1431
  return;
1296
1432
  }