aicodeman 0.3.0 → 0.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 (183) hide show
  1. package/README.md +27 -4
  2. package/dist/config/server-timing.d.ts +8 -2
  3. package/dist/config/server-timing.d.ts.map +1 -1
  4. package/dist/config/server-timing.js +8 -2
  5. package/dist/config/server-timing.js.map +1 -1
  6. package/dist/hooks-config.d.ts +21 -6
  7. package/dist/hooks-config.d.ts.map +1 -1
  8. package/dist/hooks-config.js +21 -6
  9. package/dist/hooks-config.js.map +1 -1
  10. package/dist/prompts/planner.d.ts +7 -8
  11. package/dist/prompts/planner.d.ts.map +1 -1
  12. package/dist/prompts/planner.js +7 -8
  13. package/dist/prompts/planner.js.map +1 -1
  14. package/dist/prompts/research-agent.d.ts +6 -4
  15. package/dist/prompts/research-agent.d.ts.map +1 -1
  16. package/dist/prompts/research-agent.js +6 -4
  17. package/dist/prompts/research-agent.js.map +1 -1
  18. package/dist/ralph-loop.d.ts +14 -4
  19. package/dist/ralph-loop.d.ts.map +1 -1
  20. package/dist/ralph-loop.js +14 -4
  21. package/dist/ralph-loop.js.map +1 -1
  22. package/dist/ralph-tracker.d.ts +28 -11
  23. package/dist/ralph-tracker.d.ts.map +1 -1
  24. package/dist/ralph-tracker.js +43 -13
  25. package/dist/ralph-tracker.js.map +1 -1
  26. package/dist/respawn-controller.d.ts +23 -14
  27. package/dist/respawn-controller.d.ts.map +1 -1
  28. package/dist/respawn-controller.js +23 -14
  29. package/dist/respawn-controller.js.map +1 -1
  30. package/dist/session-manager.d.ts +17 -5
  31. package/dist/session-manager.d.ts.map +1 -1
  32. package/dist/session-manager.js +17 -5
  33. package/dist/session-manager.js.map +1 -1
  34. package/dist/session.d.ts +21 -8
  35. package/dist/session.d.ts.map +1 -1
  36. package/dist/session.js +21 -8
  37. package/dist/session.js.map +1 -1
  38. package/dist/state-store.d.ts +17 -7
  39. package/dist/state-store.d.ts.map +1 -1
  40. package/dist/state-store.js +17 -7
  41. package/dist/state-store.js.map +1 -1
  42. package/dist/subagent-watcher.d.ts +23 -3
  43. package/dist/subagent-watcher.d.ts.map +1 -1
  44. package/dist/subagent-watcher.js +23 -3
  45. package/dist/subagent-watcher.js.map +1 -1
  46. package/dist/tunnel-manager.d.ts.map +1 -1
  47. package/dist/tunnel-manager.js +1 -2
  48. package/dist/tunnel-manager.js.map +1 -1
  49. package/dist/types/api.d.ts +16 -1
  50. package/dist/types/api.d.ts.map +1 -1
  51. package/dist/types/api.js +16 -1
  52. package/dist/types/api.js.map +1 -1
  53. package/dist/types/app-state.d.ts +18 -1
  54. package/dist/types/app-state.d.ts.map +1 -1
  55. package/dist/types/app-state.js +18 -1
  56. package/dist/types/app-state.js.map +1 -1
  57. package/dist/types/common.d.ts +10 -1
  58. package/dist/types/common.d.ts.map +1 -1
  59. package/dist/types/common.js +10 -1
  60. package/dist/types/common.js.map +1 -1
  61. package/dist/types/index.d.ts +50 -2
  62. package/dist/types/index.d.ts.map +1 -1
  63. package/dist/types/index.js +50 -2
  64. package/dist/types/index.js.map +1 -1
  65. package/dist/types/lifecycle.d.ts +12 -1
  66. package/dist/types/lifecycle.d.ts.map +1 -1
  67. package/dist/types/lifecycle.js +12 -1
  68. package/dist/types/lifecycle.js.map +1 -1
  69. package/dist/types/plan.d.ts +14 -1
  70. package/dist/types/plan.d.ts.map +1 -1
  71. package/dist/types/plan.js +14 -1
  72. package/dist/types/plan.js.map +1 -1
  73. package/dist/types/push.d.ts +14 -1
  74. package/dist/types/push.d.ts.map +1 -1
  75. package/dist/types/push.js +14 -1
  76. package/dist/types/push.js.map +1 -1
  77. package/dist/types/ralph.d.ts +22 -1
  78. package/dist/types/ralph.d.ts.map +1 -1
  79. package/dist/types/ralph.js +22 -1
  80. package/dist/types/ralph.js.map +1 -1
  81. package/dist/types/respawn.d.ts +22 -1
  82. package/dist/types/respawn.d.ts.map +1 -1
  83. package/dist/types/respawn.js +22 -1
  84. package/dist/types/respawn.js.map +1 -1
  85. package/dist/types/run-summary.d.ts +16 -1
  86. package/dist/types/run-summary.d.ts.map +1 -1
  87. package/dist/types/run-summary.js +16 -1
  88. package/dist/types/run-summary.js.map +1 -1
  89. package/dist/types/session.d.ts +23 -1
  90. package/dist/types/session.d.ts.map +1 -1
  91. package/dist/types/session.js +23 -1
  92. package/dist/types/session.js.map +1 -1
  93. package/dist/types/task.d.ts +15 -1
  94. package/dist/types/task.d.ts.map +1 -1
  95. package/dist/types/task.js +15 -1
  96. package/dist/types/task.js.map +1 -1
  97. package/dist/types/teams.d.ts +19 -1
  98. package/dist/types/teams.d.ts.map +1 -1
  99. package/dist/types/teams.js +19 -1
  100. package/dist/types/teams.js.map +1 -1
  101. package/dist/types/tools.d.ts +16 -1
  102. package/dist/types/tools.d.ts.map +1 -1
  103. package/dist/types/tools.js +16 -1
  104. package/dist/types/tools.js.map +1 -1
  105. package/dist/types.d.ts +11 -0
  106. package/dist/types.d.ts.map +1 -1
  107. package/dist/types.js +11 -0
  108. package/dist/types.js.map +1 -1
  109. package/dist/web/public/api-client.js +12 -0
  110. package/dist/web/public/api-client.js.br +0 -0
  111. package/dist/web/public/api-client.js.gz +0 -0
  112. package/dist/web/public/app.js +103 -103
  113. package/dist/web/public/app.js.br +0 -0
  114. package/dist/web/public/app.js.gz +0 -0
  115. package/dist/web/public/constants.js +133 -6
  116. package/dist/web/public/constants.js.br +0 -0
  117. package/dist/web/public/constants.js.gz +0 -0
  118. package/dist/web/public/index.html +14 -10
  119. package/dist/web/public/index.html.br +0 -0
  120. package/dist/web/public/index.html.gz +0 -0
  121. package/dist/web/public/keyboard-accessory.js +27 -4
  122. package/dist/web/public/keyboard-accessory.js.br +0 -0
  123. package/dist/web/public/keyboard-accessory.js.gz +0 -0
  124. package/dist/web/public/mobile-handlers.js +30 -6
  125. package/dist/web/public/mobile-handlers.js.br +0 -0
  126. package/dist/web/public/mobile-handlers.js.gz +0 -0
  127. package/dist/web/public/mobile.css.gz +0 -0
  128. package/dist/web/public/notification-manager.js +27 -0
  129. package/dist/web/public/notification-manager.js.br +0 -0
  130. package/dist/web/public/notification-manager.js.gz +0 -0
  131. package/dist/web/public/ralph-wizard.js +30 -6
  132. package/dist/web/public/ralph-wizard.js.br +0 -0
  133. package/dist/web/public/ralph-wizard.js.gz +0 -0
  134. package/dist/web/public/styles.css.gz +0 -0
  135. package/dist/web/public/subagent-windows.js +46 -12
  136. package/dist/web/public/subagent-windows.js.br +0 -0
  137. package/dist/web/public/subagent-windows.js.gz +0 -0
  138. package/dist/web/public/sw.js +15 -0
  139. package/dist/web/public/sw.js.br +0 -0
  140. package/dist/web/public/sw.js.gz +0 -0
  141. package/dist/web/public/upload.html.gz +0 -0
  142. package/dist/web/public/vendor/xterm-addon-fit.min.js.gz +0 -0
  143. package/dist/web/public/vendor/xterm-addon-unicode11.min.js.gz +0 -0
  144. package/dist/web/public/vendor/xterm-addon-webgl.min.js.gz +0 -0
  145. package/dist/web/public/vendor/xterm-zerolag-input.js +4 -0
  146. package/dist/web/public/vendor/xterm-zerolag-input.js.br +0 -0
  147. package/dist/web/public/vendor/xterm-zerolag-input.js.gz +0 -0
  148. package/dist/web/public/vendor/xterm.css.gz +0 -0
  149. package/dist/web/public/vendor/xterm.min.js.gz +0 -0
  150. package/dist/web/public/voice-input.js +26 -2
  151. package/dist/web/public/voice-input.js.br +0 -0
  152. package/dist/web/public/voice-input.js.gz +0 -0
  153. package/dist/web/route-helpers.d.ts.map +1 -1
  154. package/dist/web/route-helpers.js +3 -2
  155. package/dist/web/route-helpers.js.map +1 -1
  156. package/dist/web/routes/case-routes.d.ts.map +1 -1
  157. package/dist/web/routes/case-routes.js +11 -4
  158. package/dist/web/routes/case-routes.js.map +1 -1
  159. package/dist/web/routes/plan-routes.d.ts.map +1 -1
  160. package/dist/web/routes/plan-routes.js +26 -22
  161. package/dist/web/routes/plan-routes.js.map +1 -1
  162. package/dist/web/routes/ralph-routes.d.ts.map +1 -1
  163. package/dist/web/routes/ralph-routes.js +16 -6
  164. package/dist/web/routes/ralph-routes.js.map +1 -1
  165. package/dist/web/routes/respawn-routes.d.ts.map +1 -1
  166. package/dist/web/routes/respawn-routes.js +25 -15
  167. package/dist/web/routes/respawn-routes.js.map +1 -1
  168. package/dist/web/routes/session-routes.d.ts.map +1 -1
  169. package/dist/web/routes/session-routes.js +40 -18
  170. package/dist/web/routes/session-routes.js.map +1 -1
  171. package/dist/web/routes/system-routes.d.ts.map +1 -1
  172. package/dist/web/routes/system-routes.js +26 -5
  173. package/dist/web/routes/system-routes.js.map +1 -1
  174. package/dist/web/server.d.ts +25 -6
  175. package/dist/web/server.d.ts.map +1 -1
  176. package/dist/web/server.js +237 -156
  177. package/dist/web/server.js.map +1 -1
  178. package/dist/web/sse-events.d.ts +361 -0
  179. package/dist/web/sse-events.d.ts.map +1 -0
  180. package/dist/web/sse-events.js +396 -0
  181. package/dist/web/sse-events.js.map +1 -0
  182. package/package.json +2 -1
  183. package/scripts/postinstall.js +58 -0
Binary file
Binary file
@@ -1,8 +1,29 @@
1
+ /**
2
+ * @fileoverview Shared constants, utility functions, and SSE event type registry for all frontend modules.
3
+ *
4
+ * This is the first script loaded in index.html. Every other frontend module depends on the
5
+ * globals defined here: timing constants, Z-index layers, DEC 2026 sync markers, respawn
6
+ * preset definitions, the SSE_EVENTS registry, and shared utilities (escapeHtml, extractSyncSegments,
7
+ * getEventCoords, scheduleBackground, urlBase64ToUint8Array).
8
+ *
9
+ * @globals {function} urlBase64ToUint8Array - VAPID key conversion for Web Push
10
+ * @globals {function} scheduleBackground - scheduler.postTask wrapper (background priority)
11
+ * @globals {function} extractSyncSegments - DEC 2026 terminal sync marker parser
12
+ * @globals {function} getEventCoords - Unified mouse/touch coordinate extractor
13
+ * @globals {function} escapeHtml - XSS-safe HTML escaping
14
+ * @globals {object} SSE_EVENTS - Centralized SSE event type constants (~73 event types)
15
+ * @globals {Array} BUILTIN_RESPAWN_PRESETS - Built-in respawn configuration presets
16
+ *
17
+ * @dependency None (first in load order)
18
+ * @loadorder 1 of 9 — constants.js → mobile-handlers.js → voice-input.js → notification-manager.js
19
+ * → keyboard-accessory.js → app.js → ralph-wizard.js → api-client.js → subagent-windows.js
20
+ */
21
+
1
22
  // Codeman — Shared constants and utility functions for frontend modules
2
23
 
3
- // ============================================================================
24
+ // ═══════════════════════════════════════════════════════════════
4
25
  // Web Push Utilities
5
- // ============================================================================
26
+ // ═══════════════════════════════════════════════════════════════
6
27
 
7
28
  /** Convert a base64-encoded VAPID key to Uint8Array for pushManager.subscribe() */
8
29
  function urlBase64ToUint8Array(base64String) {
@@ -16,9 +37,9 @@ function urlBase64ToUint8Array(base64String) {
16
37
  return outputArray;
17
38
  }
18
39
 
19
- // ============================================================================
40
+ // ═══════════════════════════════════════════════════════════════
20
41
  // Constants
21
- // ============================================================================
42
+ // ═══════════════════════════════════════════════════════════════
22
43
 
23
44
  // Default terminal scrollback (can be changed via settings)
24
45
  const DEFAULT_SCROLLBACK = 5000;
@@ -157,9 +178,115 @@ const BUILTIN_RESPAWN_PRESETS = [
157
178
  },
158
179
  ];
159
180
 
160
- // ============================================================================
181
+ // ═══════════════════════════════════════════════════════════════
182
+ // SSE Event Types
183
+ // ═══════════════════════════════════════════════════════════════
184
+
185
+ /** @type {Record<string, string>} Centralized SSE event type constants */
186
+ const SSE_EVENTS = {
187
+ // Core
188
+ INIT: 'init',
189
+
190
+ // Session lifecycle
191
+ SESSION_CREATED: 'session:created',
192
+ SESSION_UPDATED: 'session:updated',
193
+ SESSION_DELETED: 'session:deleted',
194
+ SESSION_TERMINAL: 'session:terminal',
195
+ SESSION_NEEDS_REFRESH: 'session:needsRefresh',
196
+ SESSION_CLEAR_TERMINAL: 'session:clearTerminal',
197
+ SESSION_COMPLETION: 'session:completion',
198
+ SESSION_ERROR: 'session:error',
199
+ SESSION_EXIT: 'session:exit',
200
+ SESSION_IDLE: 'session:idle',
201
+ SESSION_WORKING: 'session:working',
202
+ SESSION_AUTO_CLEAR: 'session:autoClear',
203
+ SESSION_CLI_INFO: 'session:cliInfo',
204
+
205
+ // Scheduled runs
206
+ SCHEDULED_CREATED: 'scheduled:created',
207
+ SCHEDULED_UPDATED: 'scheduled:updated',
208
+ SCHEDULED_COMPLETED: 'scheduled:completed',
209
+ SCHEDULED_STOPPED: 'scheduled:stopped',
210
+
211
+ // Respawn
212
+ RESPAWN_STARTED: 'respawn:started',
213
+ RESPAWN_STOPPED: 'respawn:stopped',
214
+ RESPAWN_STATE_CHANGED: 'respawn:stateChanged',
215
+ RESPAWN_CYCLE_STARTED: 'respawn:cycleStarted',
216
+ RESPAWN_BLOCKED: 'respawn:blocked',
217
+ RESPAWN_AUTO_ACCEPT_SENT: 'respawn:autoAcceptSent',
218
+ RESPAWN_DETECTION_UPDATE: 'respawn:detectionUpdate',
219
+ RESPAWN_TIMER_STARTED: 'respawn:timerStarted',
220
+ RESPAWN_TIMER_CANCELLED: 'respawn:timerCancelled',
221
+ RESPAWN_TIMER_COMPLETED: 'respawn:timerCompleted',
222
+ RESPAWN_ERROR: 'respawn:error',
223
+ RESPAWN_ACTION_LOG: 'respawn:actionLog',
224
+
225
+ // Tasks
226
+ TASK_CREATED: 'task:created',
227
+ TASK_COMPLETED: 'task:completed',
228
+ TASK_FAILED: 'task:failed',
229
+ TASK_UPDATED: 'task:updated',
230
+
231
+ // Mux (tmux)
232
+ MUX_CREATED: 'mux:created',
233
+ MUX_KILLED: 'mux:killed',
234
+ MUX_DIED: 'mux:died',
235
+ MUX_STATS_UPDATED: 'mux:statsUpdated',
236
+
237
+ // Ralph
238
+ SESSION_RALPH_LOOP_UPDATE: 'session:ralphLoopUpdate',
239
+ SESSION_RALPH_TODO_UPDATE: 'session:ralphTodoUpdate',
240
+ SESSION_RALPH_COMPLETION_DETECTED: 'session:ralphCompletionDetected',
241
+ SESSION_RALPH_STATUS_UPDATE: 'session:ralphStatusUpdate',
242
+ SESSION_CIRCUIT_BREAKER_UPDATE: 'session:circuitBreakerUpdate',
243
+ SESSION_EXIT_GATE_MET: 'session:exitGateMet',
244
+
245
+ // Bash tools
246
+ SESSION_BASH_TOOL_START: 'session:bashToolStart',
247
+ SESSION_BASH_TOOL_END: 'session:bashToolEnd',
248
+ SESSION_BASH_TOOLS_UPDATE: 'session:bashToolsUpdate',
249
+
250
+ // Hooks (Claude Code hook events)
251
+ HOOK_IDLE_PROMPT: 'hook:idle_prompt',
252
+ HOOK_PERMISSION_PROMPT: 'hook:permission_prompt',
253
+ HOOK_ELICITATION_DIALOG: 'hook:elicitation_dialog',
254
+ HOOK_STOP: 'hook:stop',
255
+ HOOK_TEAMMATE_IDLE: 'hook:teammate_idle',
256
+ HOOK_TASK_COMPLETED: 'hook:task_completed',
257
+
258
+ // Subagents (Claude Code background agents)
259
+ SUBAGENT_DISCOVERED: 'subagent:discovered',
260
+ SUBAGENT_UPDATED: 'subagent:updated',
261
+ SUBAGENT_TOOL_CALL: 'subagent:tool_call',
262
+ SUBAGENT_PROGRESS: 'subagent:progress',
263
+ SUBAGENT_MESSAGE: 'subagent:message',
264
+ SUBAGENT_TOOL_RESULT: 'subagent:tool_result',
265
+ SUBAGENT_COMPLETED: 'subagent:completed',
266
+
267
+ // Images
268
+ IMAGE_DETECTED: 'image:detected',
269
+
270
+ // Tunnel
271
+ TUNNEL_STARTED: 'tunnel:started',
272
+ TUNNEL_STOPPED: 'tunnel:stopped',
273
+ TUNNEL_PROGRESS: 'tunnel:progress',
274
+ TUNNEL_ERROR: 'tunnel:error',
275
+ TUNNEL_QR_ROTATED: 'tunnel:qrRotated',
276
+ TUNNEL_QR_REGENERATED: 'tunnel:qrRegenerated',
277
+ TUNNEL_QR_AUTH_USED: 'tunnel:qrAuthUsed',
278
+
279
+ // Plan orchestration
280
+ PLAN_SUBAGENT: 'plan:subagent',
281
+ PLAN_PROGRESS: 'plan:progress',
282
+ PLAN_STARTED: 'plan:started',
283
+ PLAN_CANCELLED: 'plan:cancelled',
284
+ PLAN_COMPLETED: 'plan:completed',
285
+ };
286
+
287
+ // ═══════════════════════════════════════════════════════════════
161
288
  // Utility Functions
162
- // ============================================================================
289
+ // ═══════════════════════════════════════════════════════════════
163
290
 
164
291
  /**
165
292
  * Get unified coordinates from mouse or touch event.
Binary file
Binary file
@@ -20,7 +20,7 @@
20
20
  <script defer src="vendor/xterm-addon-fit.min.js"></script>
21
21
  <script defer src="vendor/xterm-addon-webgl.min.js"></script>
22
22
  <script defer src="vendor/xterm-addon-unicode11.min.js"></script>
23
- <script defer src="vendor/xterm-zerolag-input.js?v=0.2.9"></script>
23
+ <script defer src="vendor/xterm-zerolag-input.js?v=0.3.0"></script>
24
24
  <!-- Synchronous mobile detection — runs before first paint to prevent panel flash -->
25
25
  <script>if(window.innerWidth<768||(('ontouchstart' in window||navigator.maxTouchPoints>0)&&window.innerWidth<1024))document.documentElement.classList.add('mobile-init');</script>
26
26
  <!-- Inline critical CSS for instant skeleton paint (before styles.css loads) -->
@@ -961,6 +961,10 @@
961
961
  <button class="btn-icon-sm" id="tunnelQrBtn" onclick="app.showTunnelQR()" title="Show QR code" style="font-size:16px; padding:2px 6px; background:none; border:1px solid var(--border); border-radius:4px; cursor:pointer; color:var(--text-secondary)">⊞</button>
962
962
  </div>
963
963
  </div>
964
+ <div class="settings-item" id="tunnelUploadUrlRow" style="display:none">
965
+ <span class="settings-item-label">Upload URL</span>
966
+ <span id="tunnelUploadUrlDisplay" class="settings-item-value" style="cursor:pointer; text-decoration:underline; font-family:monospace; font-size:12px" title="Click to copy"></span>
967
+ </div>
964
968
 
965
969
  </div>
966
970
  </div>
@@ -1670,14 +1674,14 @@
1670
1674
  <!-- Lines drawn dynamically -->
1671
1675
  </svg>
1672
1676
 
1673
- <script defer src="constants.js?v=0.2.9"></script>
1674
- <script defer src="mobile-handlers.js?v=0.2.9"></script>
1675
- <script defer src="voice-input.js?v=0.2.9"></script>
1676
- <script defer src="notification-manager.js?v=0.2.9"></script>
1677
- <script defer src="keyboard-accessory.js?v=0.2.9"></script>
1678
- <script defer src="app.js?v=0.2.9"></script>
1679
- <script defer src="ralph-wizard.js?v=0.2.9"></script>
1680
- <script defer src="api-client.js?v=0.2.9"></script>
1681
- <script defer src="subagent-windows.js?v=0.2.9"></script>
1677
+ <script defer src="constants.js?v=0.3.0"></script>
1678
+ <script defer src="mobile-handlers.js?v=0.3.0"></script>
1679
+ <script defer src="voice-input.js?v=0.3.0"></script>
1680
+ <script defer src="notification-manager.js?v=0.3.0"></script>
1681
+ <script defer src="keyboard-accessory.js?v=0.3.0"></script>
1682
+ <script defer src="app.js?v=0.3.0"></script>
1683
+ <script defer src="ralph-wizard.js?v=0.3.0"></script>
1684
+ <script defer src="api-client.js?v=0.3.0"></script>
1685
+ <script defer src="subagent-windows.js?v=0.3.0"></script>
1682
1686
  </body>
1683
1687
  </html>
Binary file
Binary file
@@ -1,9 +1,32 @@
1
+ /**
2
+ * @fileoverview Mobile keyboard accessory bar and modal focus trap.
3
+ *
4
+ * Defines two exports:
5
+ *
6
+ * - KeyboardAccessoryBar (singleton object) — Quick action buttons shown above the virtual
7
+ * keyboard on mobile: arrow up/down, /init, /clear, /compact, paste, and dismiss.
8
+ * Destructive actions (/clear, /compact) require double-tap confirmation (2s amber state).
9
+ * Commands are sent as text + Enter separately for Ink compatibility.
10
+ * Only initializes on touch devices (MobileDetection.isTouchDevice guard).
11
+ *
12
+ * - FocusTrap (class) — Traps Tab/Shift+Tab keyboard focus within a modal element.
13
+ * Saves and restores previously focused element on deactivate. Used by Ralph wizard
14
+ * and other modal dialogs.
15
+ *
16
+ * @globals {object} KeyboardAccessoryBar
17
+ * @globals {class} FocusTrap
18
+ *
19
+ * @dependency mobile-handlers.js (MobileDetection.isTouchDevice)
20
+ * @dependency app.js (uses global `app` for sendInput, activeSessionId, terminal)
21
+ * @loadorder 5 of 9 — loaded after notification-manager.js, before app.js
22
+ */
23
+
1
24
  // Codeman — Keyboard accessory bar and focus trap for modals
2
25
  // Loaded after mobile-handlers.js, before app.js
3
26
 
4
- // ============================================================================
27
+ // ═══════════════════════════════════════════════════════════════
5
28
  // Mobile Keyboard Accessory Bar
6
- // ============================================================================
29
+ // ═══════════════════════════════════════════════════════════════
7
30
 
8
31
  /**
9
32
  * KeyboardAccessoryBar - Quick action buttons shown above keyboard when typing.
@@ -209,9 +232,9 @@ const KeyboardAccessoryBar = {
209
232
  }
210
233
  };
211
234
 
212
- // ============================================================================
235
+ // ═══════════════════════════════════════════════════════════════
213
236
  // Accessibility: Focus Trap for Modals
214
- // ============================================================================
237
+ // ═══════════════════════════════════════════════════════════════
215
238
 
216
239
  /**
217
240
  * FocusTrap - Traps keyboard focus within an element (typically a modal).
@@ -1,9 +1,33 @@
1
+ /**
2
+ * @fileoverview Mobile device support: detection, keyboard handling, and swipe navigation.
3
+ *
4
+ * Defines three singleton objects that manage mobile-specific behavior:
5
+ *
6
+ * - MobileDetection — Device type detection (mobile/tablet/desktop), touch capability,
7
+ * iOS/Safari identification, and body class management for CSS targeting.
8
+ * - KeyboardHandler — Virtual keyboard show/hide detection via visualViewport API,
9
+ * toolbar/accessory bar repositioning, terminal resize on keyboard open/close,
10
+ * and input scroll-into-view. Uses 100px threshold for iOS address bar drift.
11
+ * - SwipeHandler — Horizontal swipe detection on the terminal area for session switching.
12
+ * 80px minimum distance, 300ms maximum time, 100px max vertical drift.
13
+ *
14
+ * All three have init()/cleanup() lifecycle methods. They are re-initialized after SSE
15
+ * reconnect (in handleInit) to prevent stale closures.
16
+ *
17
+ * @globals {object} MobileDetection
18
+ * @globals {object} KeyboardHandler
19
+ * @globals {object} SwipeHandler
20
+ *
21
+ * @dependency keyboard-accessory.js (KeyboardAccessoryBar reference in KeyboardHandler.onKeyboardShow, soft — guarded with typeof check)
22
+ * @loadorder 2 of 9 — loaded after constants.js, before voice-input.js
23
+ */
24
+
1
25
  // Codeman — Mobile detection, keyboard handling, and swipe navigation
2
26
  // Loaded after constants.js, before app.js
3
27
 
4
- // ============================================================================
28
+ // ═══════════════════════════════════════════════════════════════
5
29
  // Mobile Detection
6
- // ============================================================================
30
+ // ═══════════════════════════════════════════════════════════════
7
31
 
8
32
  /**
9
33
  * MobileDetection - Detects device type and touch capability.
@@ -109,9 +133,9 @@ const MobileDetection = {
109
133
  }
110
134
  };
111
135
 
112
- // ============================================================================
136
+ // ═══════════════════════════════════════════════════════════════
113
137
  // Mobile Keyboard Handler
114
- // ============================================================================
138
+ // ═══════════════════════════════════════════════════════════════
115
139
 
116
140
  /**
117
141
  * KeyboardHandler - Simple handler to scroll inputs into view when keyboard appears.
@@ -387,9 +411,9 @@ const KeyboardHandler = {
387
411
  }
388
412
  };
389
413
 
390
- // ============================================================================
414
+ // ═══════════════════════════════════════════════════════════════
391
415
  // Mobile Swipe Handler
392
- // ============================================================================
416
+ // ═══════════════════════════════════════════════════════════════
393
417
 
394
418
  /**
395
419
  * SwipeHandler - Detects horizontal swipes on terminal to switch sessions.
Binary file
@@ -1,3 +1,30 @@
1
+ /**
2
+ * @fileoverview Five-layer notification system for session events and alerts.
3
+ *
4
+ * The NotificationManager class implements five notification layers:
5
+ * 1. In-app notification drawer (slide-out panel with grouped notifications)
6
+ * 2. Tab title flash (alternating "(*) Codeman" when tab is hidden)
7
+ * 3. Browser Notification API (desktop push with auto-close after 8s)
8
+ * 4. Web Push via service worker (OS-level notifications when tab is closed)
9
+ * 5. Audio alerts (Web Audio API beep, user-opt-in)
10
+ *
11
+ * Features:
12
+ * - Per-event-type preferences (enabled, browser, audio, push) with v1→v4 migration
13
+ * - Device-specific defaults (notifications disabled on mobile by default)
14
+ * - 5s notification grouping window to batch rapid-fire events
15
+ * - 100-notification cap with oldest eviction
16
+ * - Rate limiting: 3s between browser notifications
17
+ * - Visibility tracking (pauses title flash when tab becomes visible)
18
+ * - iOS Safari bfcache support via pageshow event
19
+ *
20
+ * @class NotificationManager
21
+ * @param {CodemanApp} app - Reference to the main app instance
22
+ *
23
+ * @dependency constants.js (STUCK_THRESHOLD_DEFAULT_MS, timing constants)
24
+ * @dependency mobile-handlers.js (MobileDetection.getDeviceType for device-specific defaults)
25
+ * @loadorder 4 of 9 — loaded after voice-input.js, before keyboard-accessory.js
26
+ */
27
+
1
28
  // Codeman — Multi-layer notification system
2
29
  // Loaded after mobile-handlers.js, before app.js
3
30
 
@@ -1,10 +1,30 @@
1
1
  /**
2
- * Ralph Loop Wizard — extracted from app.js for maintainability.
3
- * Extends CodemanApp.prototype with wizard methods.
4
- * Loaded after app.js in index.html.
2
+ * @fileoverview Ralph Loop Wizard — multi-step modal for configuring autonomous task loops.
3
+ *
4
+ * Extends CodemanApp.prototype with wizard methods for the Ralph Loop setup flow:
5
+ * Step 1: Task description, completion phrase, iteration limit, case selection
6
+ * Step 2: AI-powered plan generation (optional) with research agent → planner agent pipeline
7
+ * Step 3: Respawn configuration (idle timeout, kickstart prompt, auto-clear/init)
8
+ * Step 4: Review and launch
9
+ *
10
+ * Features:
11
+ * - Plan generation via POST /api/sessions/:id/plan/generate with SSE progress streaming
12
+ * - Existing @fix_plan.md detection and reuse
13
+ * - Plan detail level selection (brief/detailed/comprehensive)
14
+ * - Case selector population from /api/cases
15
+ * - Focus trap for modal accessibility
16
+ * - Abort controller for cancelling in-flight plan generation
17
+ *
18
+ * @mixin Extends CodemanApp.prototype via Object.assign
19
+ * @dependency app.js (CodemanApp class must be defined)
20
+ * @dependency keyboard-accessory.js (FocusTrap class for modal focus management)
21
+ * @dependency constants.js (escapeHtml)
22
+ * @loadorder 7 of 9 — loaded after app.js, before api-client.js
5
23
  */
6
24
 
7
- // ========== Ralph Loop Wizard ==========
25
+ // ═══════════════════════════════════════════════════════════════
26
+ // Ralph Loop Wizard
27
+ // ═══════════════════════════════════════════════════════════════
8
28
 
9
29
  Object.assign(CodemanApp.prototype, {
10
30
 
@@ -388,7 +408,9 @@ Object.assign(CodemanApp.prototype, {
388
408
  }
389
409
  },
390
410
 
391
- // ========== Plan Generation ==========
411
+ // ═══════════════════════════════════════════════════════════════
412
+ // Plan Generation
413
+ // ═══════════════════════════════════════════════════════════════
392
414
 
393
415
  resetPlanGenerationUI() {
394
416
  // Hide all plan generation states
@@ -780,7 +802,9 @@ Object.assign(CodemanApp.prototype, {
780
802
  this.closePlanSubagentWindows();
781
803
  },
782
804
 
783
- // ========== Plan Subagent Windows ==========
805
+ // ═══════════════════════════════════════════════════════════════
806
+ // Plan Subagent Windows
807
+ // ═══════════════════════════════════════════════════════════════
784
808
 
785
809
  handlePlanSubagentEvent(event) {
786
810
  if (this.planGenerationStopped) return;
Binary file
Binary file
Binary file
@@ -1,3 +1,23 @@
1
+ /**
2
+ * @fileoverview Subagent floating window management mixed into CodemanApp.prototype.
3
+ *
4
+ * Extends CodemanApp with methods for managing floating terminal windows that display
5
+ * Claude Code background agent (subagent) output. Each subagent window has its own
6
+ * xterm.js terminal instance, drag/resize handles, minimize/close controls, and
7
+ * connection lines drawn to the parent session tab.
8
+ *
9
+ * Key functionality:
10
+ * - Tab badge dropdown showing minimized agents per session
11
+ * - Minimize/restore/permanently-close lifecycle for subagent windows
12
+ * - Cross-browser state persistence (localStorage + server-backed PUT /api/subagent-window-states)
13
+ * - Window state saved on every minimize/restore/close action
14
+ *
15
+ * @mixin Extends CodemanApp.prototype via Object.assign
16
+ * @dependency app.js (CodemanApp class, this.subagents, this.subagentWindows, this.minimizedSubagents)
17
+ * @dependency constants.js (escapeHtml)
18
+ * @loadorder 9 of 9 — loaded last, after api-client.js
19
+ */
20
+
1
21
  // Codeman — Subagent window management for CodemanApp
2
22
  // Loaded after app.js (needs CodemanApp class defined)
3
23
 
@@ -80,7 +100,9 @@ Object.assign(CodemanApp.prototype, {
80
100
  this.saveSubagentWindowStates();
81
101
  },
82
102
 
83
- // ========== Subagent Window State Persistence ==========
103
+ // ═══════════════════════════════════════════════════════════════
104
+ // Subagent Window State Persistence
105
+ // ═══════════════════════════════════════════════════════════════
84
106
 
85
107
  /**
86
108
  * Save subagent window states (minimized/open) to server for cross-browser persistence.
@@ -198,7 +220,9 @@ Object.assign(CodemanApp.prototype, {
198
220
  });
199
221
  },
200
222
 
201
- // ========== Subagent Connection Lines ==========
223
+ // ═══════════════════════════════════════════════════════════════
224
+ // Subagent Connection Lines
225
+ // ═══════════════════════════════════════════════════════════════
202
226
  //
203
227
  // Connection lines are drawn from agent windows to their parent TABs.
204
228
  // The parent TAB is determined by the PERSISTENT subagentParentMap.
@@ -434,7 +458,9 @@ Object.assign(CodemanApp.prototype, {
434
458
  }
435
459
  },
436
460
 
437
- // ========== Subagent Floating Windows ==========
461
+ // ═══════════════════════════════════════════════════════════════
462
+ // Subagent Floating Windows
463
+ // ═══════════════════════════════════════════════════════════════
438
464
 
439
465
  openSubagentWindow(agentId) {
440
466
  // If window already exists, focus it
@@ -986,19 +1012,20 @@ Object.assign(CodemanApp.prototype, {
986
1012
  }
987
1013
  };
988
1014
 
989
- // Mouse events
990
- handle.addEventListener('mousedown', (e) => {
1015
+ // Named handle-level listeners (stored for explicit cleanup on window close)
1016
+ const handleMouseDown = (e) => {
991
1017
  if (e.target.tagName === 'BUTTON') return;
992
1018
  startDrag(e.clientX, e.clientY);
993
1019
  e.preventDefault();
994
- });
995
-
996
- // Touch events
997
- handle.addEventListener('touchstart', (e) => {
1020
+ };
1021
+ const handleTouchStart = (e) => {
998
1022
  if (e.target.tagName === 'BUTTON') return;
999
1023
  const touch = e.touches[0];
1000
1024
  startDrag(touch.clientX, touch.clientY);
1001
- }, { passive: true });
1025
+ };
1026
+
1027
+ handle.addEventListener('mousedown', handleMouseDown);
1028
+ handle.addEventListener('touchstart', handleTouchStart, { passive: true });
1002
1029
 
1003
1030
  // Store references to document-level listeners so they can be removed on window close
1004
1031
  const moveListener = (e) => {
@@ -1022,8 +1049,15 @@ Object.assign(CodemanApp.prototype, {
1022
1049
  document.addEventListener('touchend', upListener);
1023
1050
  document.addEventListener('touchcancel', upListener);
1024
1051
 
1025
- // Return listener references for cleanup
1026
- return { move: moveListener, up: upListener, touchMove: touchMoveListener };
1052
+ // Return all listener references for cleanup (both handle-level and document-level)
1053
+ return {
1054
+ move: moveListener,
1055
+ up: upListener,
1056
+ touchMove: touchMoveListener,
1057
+ handle,
1058
+ handleMouseDown,
1059
+ handleTouchStart,
1060
+ };
1027
1061
  },
1028
1062
 
1029
1063
  // Show subagent dropdown on hover
@@ -1,3 +1,18 @@
1
+ /**
2
+ * @fileoverview Service worker for Web Push notifications.
3
+ *
4
+ * Receives push events from the Codeman server (via web-push library) and displays
5
+ * OS-level notifications. Handles notification clicks to focus an existing Codeman
6
+ * tab or open a new one. Supports action buttons, per-session deep linking, and
7
+ * critical notification persistence (requireInteraction).
8
+ *
9
+ * Lifecycle: skipWaiting on install, claim clients on activate — ensures the latest
10
+ * service worker takes control immediately without waiting for tab refresh.
11
+ *
12
+ * @dependency None (runs in ServiceWorkerGlobalScope, isolated from page scripts)
13
+ * @see src/push-store.ts — server-side VAPID key management and subscription CRUD
14
+ */
15
+
1
16
  // Codeman Service Worker — Web Push notifications
2
17
  // This service worker receives push events from the server and displays OS-level notifications.
3
18
  // It also handles notification clicks to focus or open the Codeman tab.
Binary file
Binary file
Binary file
@@ -0,0 +1,4 @@
1
+ "use strict";var XtermZerolagInput=(()=>{var x=Object.defineProperty;var F=Object.getOwnPropertyDescriptor;var L=Object.getOwnPropertyNames;var R=Object.prototype.hasOwnProperty;var E=(r,t)=>{for(var s in t)x(r,s,{get:t[s],enumerable:!0})},H=(r,t,s,e)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of L(t))!R.call(r,i)&&i!==s&&x(r,i,{get:()=>t[i],enumerable:!(e=F(t,i))||e.enumerable});return r};var k=r=>H(x({},"__esModule",{value:!0}),r);var B={};E(B,{ZerolagInputAddon:()=>P});function w(r){let t=r,s=typeof devicePixelRatio=="number"&&devicePixelRatio>0?devicePixelRatio:1;if(t.dimensions?.css?.cell){let e=t.dimensions.css.cell.height;return{width:t.dimensions.css.cell.width,height:e,charTop:(t.dimensions?.device?.char?.top??0)/s,charHeight:(t.dimensions?.device?.char?.height??e*s)/s}}try{let e=t._core?._renderService?.dimensions;if(e?.css?.cell){let i=e.css.cell.height;return{width:e.css.cell.width,height:i,charTop:(e.device?.char?.top??0)/s,charHeight:(e.device?.char?.height??i*s)/s}}}catch{}return null}function C(r,t){try{let s=r.buffer.active,e=s.viewportY;switch(t.type){case"character":{for(let i=r.rows-1;i>=0;i--){let l=s.getLine(e+i);if(!l)continue;let p=l.translateToString(!0).lastIndexOf(t.char);if(p>=0)return{row:i,col:p}}return null}case"regex":{let i=t.pattern,l=i.global?new RegExp(i.source,i.flags.replace("g","")):i;for(let h=r.rows-1;h>=0;h--){let p=s.getLine(e+h);if(!p)continue;let o=p.translateToString(!0).match(l);if(o){let d=o.index??0;return{row:h,col:d}}}return null}case"custom":return t.find(r);default:return null}}catch{return null}}function T(r,t,s){try{let e=r.buffer.active,i=e.viewportY+t.row,l=e.getLine(i);return l?l.translateToString(!0).slice(t.col+s).trimEnd():""}catch{return""}}function O(r,t){let{lines:s,startCol:e,totalCols:i,cellW:l,cellH:h,charTop:p,charHeight:f,promptRow:o,font:d,showCursor:n,cursorColor:m}=t;r.style.left="0px",r.style.top=o*h+"px",r.innerHTML="";let g=i*l;for(let a=0;a<s.length;a++){let _=a===0?e*l:0,c=a===0?g-_:g,u=a*h,y=M(s[a],_,u,c,h,l,p,f,d);r.appendChild(y)}if(n){let a=s[s.length-1],c=(s.length===1?e:0)+a.length;if(c<i){let u=document.createElement("span");u.style.cssText="position:absolute;display:inline-block",u.style.left=c*l+"px",u.style.top=(s.length-1)*h+"px",u.style.width=l+"px",u.style.height=h+"px",u.style.backgroundColor=m,r.appendChild(u)}}r.style.display=""}function M(r,t,s,e,i,l,h,p,f){let o=document.createElement("div");o.style.cssText="position:absolute;pointer-events:none",o.style.backgroundColor=f.backgroundColor,o.style.left=t+"px",o.style.top=s+"px",o.style.width=e+"px",o.style.height=i+1+"px";for(let d=0;d<r.length;d++){let n=document.createElement("span");n.style.cssText="position:absolute;display:inline-block;text-align:center;pointer-events:none;font-feature-settings:'liga' 0,'calt' 0",n.style.left=d*l+"px",n.style.top="0px",n.style.width=l+"px",n.style.height=i+"px",n.style.lineHeight=i+"px",n.style.fontFamily=f.fontFamily,n.style.fontSize=f.fontSize,n.style.fontWeight=f.fontWeight,n.style.color=f.color,f.letterSpacing&&(n.style.letterSpacing=f.letterSpacing),n.textContent=r[d],o.appendChild(n)}return o}var v={type:"character",char:">",offset:2},I=7,X=50,D="#0d0d0d",S="#eeeeee",z="#e0e0e0",P=class{_terminal=null;_overlay=null;_options;_pendingText="";_flushedOffset=0;_flushedText="";_bufferDetectDone=!1;_lastRenderKey="";_lastPromptPos=null;_font={fontFamily:"monospace",fontSize:"14px",fontWeight:"normal",color:S,backgroundColor:D,letterSpacing:""};_scrollTimer=null;_scrollHandler=null;_scrollViewport=null;constructor(t){this._options={prompt:t?.prompt??v,zIndex:t?.zIndex??I,showCursor:t?.showCursor??!0,scrollDebounceMs:t?.scrollDebounceMs??X,backgroundColor:t?.backgroundColor,foregroundColor:t?.foregroundColor,cursorColor:t?.cursorColor}}activate(t){this._terminal=t,this._overlay=document.createElement("div"),this._overlay.style.cssText=`position:absolute;z-index:${this._options.zIndex};pointer-events:none;display:none`;let s=t.element?.querySelector(".xterm-screen");s&&s.appendChild(this._overlay),this._cacheFont(),this._scrollHandler=()=>{try{let i=this._terminal.buffer.active;i.viewportY!==i.baseY?(this._overlay.style.display="none",this._scrollTimer&&(clearTimeout(this._scrollTimer),this._scrollTimer=null)):(this._pendingText||this._flushedOffset>0)&&(this._scrollTimer&&clearTimeout(this._scrollTimer),this._scrollTimer=setTimeout(()=>{this._scrollTimer=null,this._lastRenderKey="",this._render()},this._options.scrollDebounceMs))}catch{}};let e=t.element?.querySelector(".xterm-viewport");e&&(e.addEventListener("scroll",this._scrollHandler,{passive:!0}),this._scrollViewport=e)}dispose(){this.clear(),this._scrollTimer&&(clearTimeout(this._scrollTimer),this._scrollTimer=null),this._scrollViewport&&this._scrollHandler&&this._scrollViewport.removeEventListener("scroll",this._scrollHandler),this._overlay?.remove(),this._overlay=null,this._scrollViewport=null,this._scrollHandler=null,this._terminal=null}addChar(t){!this._pendingText&&!this._flushedOffset&&this._detectBufferText(),this._pendingText+=t,this._render()}appendText(t){t&&(!this._pendingText&&!this._flushedOffset&&this._detectBufferText(),this._pendingText+=t,this._render())}removeChar(){return this._pendingText.length>0?(this._pendingText=this._pendingText.slice(0,-1),this._pendingText.length>0||this._flushedOffset>0?this._render():this._hide(),"pending"):this._flushedOffset>0?(this._flushedOffset--,this._flushedText=this._flushedText.slice(0,-1),this._flushedOffset>0?this._render():this._hide(),"flushed"):(this._detectBufferText(),this._flushedOffset>0?(this._flushedOffset--,this._flushedText=this._flushedText.slice(0,-1),this._flushedOffset>0?this._render():this._hide(),"flushed"):!1)}clear(){this._pendingText="",this._flushedOffset=0,this._flushedText="",this._bufferDetectDone=!1,this._lastRenderKey="",this._lastPromptPos=null,this._hide()}setFlushed(t,s,e=!0){this._flushedOffset=t,this._flushedText=s,e&&this._render()}getFlushed(){return{count:this._flushedOffset,text:this._flushedText}}clearFlushed(){this._flushedOffset=0,this._flushedText="",this._pendingText?this._render():this._hide()}rerender(){(this._pendingText||this._flushedOffset>0)&&(this._lastRenderKey="",this._render())}refreshFont(){this._cacheFont(),this._lastRenderKey="",(this._pendingText||this._flushedOffset>0)&&this._render()}detectBufferText(){return this._detectBufferText()}resetBufferDetection(){this._bufferDetectDone=!1}undoDetection(){this._flushedOffset=0,this._flushedText="",this._bufferDetectDone=!1}suppressBufferDetection(){this._bufferDetectDone=!0}setPrompt(t){this._options.prompt=t,this._lastPromptPos=null,this._lastRenderKey="",(this._pendingText||this._flushedOffset>0)&&this._render()}findPrompt(){return this._terminal?C(this._terminal,this._options.prompt??v):null}readPromptText(){if(!this._terminal)return null;let t=this.findPrompt();if(!t)return null;let s=this._getPromptOffset();return T(this._terminal,t,s)||null}get pendingText(){return this._pendingText}get hasPending(){return this._pendingText.length>0||this._flushedOffset>0}get state(){return{pendingText:this._pendingText,flushedLength:this._flushedOffset,flushedText:this._flushedText,visible:this._overlay!==null&&this._overlay.style.display!=="none",promptPosition:this._lastPromptPos?{...this._lastPromptPos}:null}}_getPromptOffset(){return(this._options.prompt??v).offset??2}_detectBufferText(){if(this._bufferDetectDone||!this._terminal)return null;try{let t=this.findPrompt();if(!t)return null;let s=this._getPromptOffset(),e=T(this._terminal,t,s);if(e.length>0)return this._flushedOffset=e.length,this._flushedText=e,this._lastPromptPos=t,this._bufferDetectDone=!0,e}catch{}return null}_cacheFont(){if(!this._terminal)return;let t=this._terminal;this._font.fontFamily=t.options.fontFamily||"monospace",this._font.fontSize=(t.options.fontSize||14)+"px",this._font.fontWeight=String(t.options.fontWeight||"normal"),this._font.backgroundColor=this._options.backgroundColor??t.options.theme?.background??D,this._font.color=this._options.foregroundColor??t.options.theme?.foreground??S,this._font.letterSpacing="";let s=t.element?.querySelector(".xterm-rows");if(s){let e=getComputedStyle(s);this._font.letterSpacing=e.letterSpacing,!this._options.foregroundColor&&e.color&&(this._font.color=e.color)}}_hide(){this._overlay&&(this._lastRenderKey="",this._lastPromptPos=null,this._overlay.innerHTML="",this._overlay.style.display="none")}_render(){if(!(!this._terminal||!this._overlay)){if(!this._pendingText&&!(this._flushedOffset>0)){this._overlay.style.display="none";return}try{let t=this._terminal.buffer.active;if(t.viewportY!==t.baseY){this._overlay.style.display="none";return}let s=this.findPrompt();if(s)this._lastPromptPos&&this._flushedOffset>0?this._lastPromptPos={row:s.row,col:this._lastPromptPos.col}:this._lastPromptPos=s;else if(!this._lastPromptPos){this._overlay.style.display="none";return}let e=this._lastPromptPos,i=w(this._terminal);if(!i){this._overlay.style.display="none";return}let{width:l,height:h,charTop:p,charHeight:f}=i,o=this._terminal.cols,d=this._getPromptOffset(),n=e.col+d,m=this._pendingText;if(this._flushedOffset>0)if(this._flushedText&&this._flushedText.length===this._flushedOffset)m=this._flushedText+this._pendingText;else{let y=t.viewportY+e.row,b=t.getLine(y);b&&(m=b.translateToString(!0).slice(n,n+this._flushedOffset)+this._pendingText)}let g=`${m}:${n}:${e.row}:${e.col}:${o}:${this._flushedOffset}`;if(g===this._lastRenderKey&&this._overlay.style.display!=="none")return;this._lastRenderKey=g;let a=Math.max(1,o-n),_=[],c=m;for(_.push(c.slice(0,a)),c=c.slice(a);c.length>0;)_.push(c.slice(0,o)),c=c.slice(o);let u=this._options.cursorColor??this._terminal.options.theme?.cursor??z;O(this._overlay,{lines:_,startCol:n,totalCols:o,cellW:l,cellH:h,charTop:p,charHeight:f,promptRow:e.row,font:this._font,showCursor:this._options.showCursor,cursorColor:u})}catch{this._overlay&&(this._overlay.innerHTML="",this._overlay.style.display="none")}}}};return k(B);})();
2
+
3
+ // Global aliases for browser usage
4
+ if(typeof window!=="undefined"){window.ZerolagInputAddon=XtermZerolagInput.ZerolagInputAddon;window.LocalEchoOverlay=class extends XtermZerolagInput.ZerolagInputAddon{constructor(terminal){super({prompt:{type:"character",char:"\u276f",offset:2}});this.activate(terminal);}};}
Binary file