mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-05 06:59:42 +02:00
refactor: SSE event handlers, LLM context optimization, @fileoverview docs (#29)
* refactor: extract SSE event handlers into named class methods Replace ~80 inline addListener closures in connectSSE() with a declarative _SSE_HANDLER_MAP array that drives registration in a single loop. Each handler is now a named _on* method on CodemanApp, making them individually addressable for LLM navigation. Add SSE_EVENTS constant object in constants.js to eliminate magic event-type strings scattered across the frontend. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: fix inaccuracies in CLAUDE.md - Fix types barrel path: src/types.ts → src/types/index.ts - Update app.js line count: ~12K → ~11.5K - Correct route handler counts (113 → 111, per-group fixes) - Add code style, ESM gotcha, env vars, route test, lifecycle log docs - Add Node 22 CI note, test teardown timeout, port range Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: add mobile screenshots and QR auth security writeup to README Add 3 mobile screenshots (landing, idle, active) and expand the mobile section with QR auth security design details and a touch-optimized interface subsection. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: bundle xterm-zerolag-input as vendor IIFE and add pre-commit hook Build and postinstall now bundle the local xterm-zerolag-input package as an IIFE at vendor/xterm-zerolag-input.js with global LocalEchoOverlay shim. Add git pre-commit hook that runs prettier --check on staged .ts files to catch format issues before CI. Also bump constants.js and app.js cache-bust versions to 0.3.0 and add tunnel upload URL display row in settings. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add cloudflared install support and interactive launch menu - Add optional cloudflared dependency detection and installation across 6 distro families (macOS, Debian, Fedora, Arch, Alpine, SUSE) - Add tunnel systemd service setup helper - Replace post-install instructions with interactive launch menu (run now / systemd service / skip) - Uninstall now cleans up both codeman-web and codeman-tunnel services Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: gitignore readme-preview.mjs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: WIP — SSE event constants, @fileoverview docs, CLAUDE.md compression - Migrate broadcast() string literals → SseEvent.* typed constants - Add @fileoverview with cross-domain references to all 13 type domain files - Add @fileoverview to frontend JS modules (constants, mobile, voice, etc.) - Add section dividers to route files for LLM scanability - Compress CLAUDE.md: flat file list → domain table, fix counts Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: optimize codebase for LLM context window efficiency CLAUDE.md: 456 → 309 lines (32% reduction) - Merge Commands into compact table, remove redundant bash block - Convert Security section to dense table format - Merge Performance + Resource Limits, Debugging + Troubleshooting - Compress Tunnel, Memory Leak, Scripts, Screenshots sections - Remove Key Patterns that duplicate @fileoverview in source files Backend @fileoverview enhancements (10 priority files): - session.ts: key methods, events, cross-domain refs - respawn-controller.ts: state machine, idle detection layers - ralph-tracker.ts: exports, circuit breaker, events - ralph-loop.ts: lifecycle, persistence, events - subagent-watcher.ts: watched patterns, teammate detection - server.ts: coordination list, port interfaces - state-store.ts: dual-file persistence, migration - session-manager.ts: lifecycle methods, mutex guard - hooks-config.ts: hook events list, categories - sse-events.ts: category breakdown (~90 events, 17 categories) Frontend app.js: add 6 section dividers, update @fileoverview line refs Fix: escape glob `*/` in JSDoc that broke ESLint parser Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: address PR #29 review bugs - server.ts: replace hardcoded 'session:needsRefresh' with SseEvent constant - install.sh: fix Alpine cloudflared install for non-root (download to tmpfile first) - install.sh: replace Arch pacman (AUR-only) with direct binary download - index.html: bump all 8 remaining cache-bust versions from v0.2.9 to v0.3.0 - mobile-handlers.js: fix @dependency annotation (keyboard-accessory.js, not constants.js) - types/push.ts: fix layer number (4, not 5) - subagent-watcher.ts: fix watched pattern path to include {session} segment - constants.js: fix SSE_EVENTS count in @fileoverview (~73, not ~65) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,3 +1,15 @@
|
||||
/**
|
||||
* @fileoverview Centralized API fetch helpers mixed into CodemanApp.prototype.
|
||||
*
|
||||
* Provides _api(), _apiJson(), _apiPost(), _apiPut(), _apiDelete() methods that handle
|
||||
* JSON serialization, Content-Type headers, and error swallowing. All API calls in the
|
||||
* frontend route through these helpers.
|
||||
*
|
||||
* @mixin Extends CodemanApp.prototype via Object.assign
|
||||
* @dependency app.js (CodemanApp class must be defined)
|
||||
* @loadorder 8 of 9 — loaded after app.js
|
||||
*/
|
||||
|
||||
// Codeman — Centralized API fetch helpers for CodemanApp
|
||||
// Loaded after app.js (needs CodemanApp class defined)
|
||||
|
||||
|
||||
+1297
-1079
File diff suppressed because it is too large
Load Diff
+133
-6
@@ -1,8 +1,29 @@
|
||||
/**
|
||||
* @fileoverview Shared constants, utility functions, and SSE event type registry for all frontend modules.
|
||||
*
|
||||
* This is the first script loaded in index.html. Every other frontend module depends on the
|
||||
* globals defined here: timing constants, Z-index layers, DEC 2026 sync markers, respawn
|
||||
* preset definitions, the SSE_EVENTS registry, and shared utilities (escapeHtml, extractSyncSegments,
|
||||
* getEventCoords, scheduleBackground, urlBase64ToUint8Array).
|
||||
*
|
||||
* @globals {function} urlBase64ToUint8Array - VAPID key conversion for Web Push
|
||||
* @globals {function} scheduleBackground - scheduler.postTask wrapper (background priority)
|
||||
* @globals {function} extractSyncSegments - DEC 2026 terminal sync marker parser
|
||||
* @globals {function} getEventCoords - Unified mouse/touch coordinate extractor
|
||||
* @globals {function} escapeHtml - XSS-safe HTML escaping
|
||||
* @globals {object} SSE_EVENTS - Centralized SSE event type constants (~73 event types)
|
||||
* @globals {Array} BUILTIN_RESPAWN_PRESETS - Built-in respawn configuration presets
|
||||
*
|
||||
* @dependency None (first in load order)
|
||||
* @loadorder 1 of 9 — constants.js → mobile-handlers.js → voice-input.js → notification-manager.js
|
||||
* → keyboard-accessory.js → app.js → ralph-wizard.js → api-client.js → subagent-windows.js
|
||||
*/
|
||||
|
||||
// Codeman — Shared constants and utility functions for frontend modules
|
||||
|
||||
// ============================================================================
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
// Web Push Utilities
|
||||
// ============================================================================
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
|
||||
/** Convert a base64-encoded VAPID key to Uint8Array for pushManager.subscribe() */
|
||||
function urlBase64ToUint8Array(base64String) {
|
||||
@@ -16,9 +37,9 @@ function urlBase64ToUint8Array(base64String) {
|
||||
return outputArray;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
// Constants
|
||||
// ============================================================================
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
|
||||
// Default terminal scrollback (can be changed via settings)
|
||||
const DEFAULT_SCROLLBACK = 5000;
|
||||
@@ -157,9 +178,115 @@ const BUILTIN_RESPAWN_PRESETS = [
|
||||
},
|
||||
];
|
||||
|
||||
// ============================================================================
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
// SSE Event Types
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
|
||||
/** @type {Record<string, string>} Centralized SSE event type constants */
|
||||
const SSE_EVENTS = {
|
||||
// Core
|
||||
INIT: 'init',
|
||||
|
||||
// Session lifecycle
|
||||
SESSION_CREATED: 'session:created',
|
||||
SESSION_UPDATED: 'session:updated',
|
||||
SESSION_DELETED: 'session:deleted',
|
||||
SESSION_TERMINAL: 'session:terminal',
|
||||
SESSION_NEEDS_REFRESH: 'session:needsRefresh',
|
||||
SESSION_CLEAR_TERMINAL: 'session:clearTerminal',
|
||||
SESSION_COMPLETION: 'session:completion',
|
||||
SESSION_ERROR: 'session:error',
|
||||
SESSION_EXIT: 'session:exit',
|
||||
SESSION_IDLE: 'session:idle',
|
||||
SESSION_WORKING: 'session:working',
|
||||
SESSION_AUTO_CLEAR: 'session:autoClear',
|
||||
SESSION_CLI_INFO: 'session:cliInfo',
|
||||
|
||||
// Scheduled runs
|
||||
SCHEDULED_CREATED: 'scheduled:created',
|
||||
SCHEDULED_UPDATED: 'scheduled:updated',
|
||||
SCHEDULED_COMPLETED: 'scheduled:completed',
|
||||
SCHEDULED_STOPPED: 'scheduled:stopped',
|
||||
|
||||
// Respawn
|
||||
RESPAWN_STARTED: 'respawn:started',
|
||||
RESPAWN_STOPPED: 'respawn:stopped',
|
||||
RESPAWN_STATE_CHANGED: 'respawn:stateChanged',
|
||||
RESPAWN_CYCLE_STARTED: 'respawn:cycleStarted',
|
||||
RESPAWN_BLOCKED: 'respawn:blocked',
|
||||
RESPAWN_AUTO_ACCEPT_SENT: 'respawn:autoAcceptSent',
|
||||
RESPAWN_DETECTION_UPDATE: 'respawn:detectionUpdate',
|
||||
RESPAWN_TIMER_STARTED: 'respawn:timerStarted',
|
||||
RESPAWN_TIMER_CANCELLED: 'respawn:timerCancelled',
|
||||
RESPAWN_TIMER_COMPLETED: 'respawn:timerCompleted',
|
||||
RESPAWN_ERROR: 'respawn:error',
|
||||
RESPAWN_ACTION_LOG: 'respawn:actionLog',
|
||||
|
||||
// Tasks
|
||||
TASK_CREATED: 'task:created',
|
||||
TASK_COMPLETED: 'task:completed',
|
||||
TASK_FAILED: 'task:failed',
|
||||
TASK_UPDATED: 'task:updated',
|
||||
|
||||
// Mux (tmux)
|
||||
MUX_CREATED: 'mux:created',
|
||||
MUX_KILLED: 'mux:killed',
|
||||
MUX_DIED: 'mux:died',
|
||||
MUX_STATS_UPDATED: 'mux:statsUpdated',
|
||||
|
||||
// Ralph
|
||||
SESSION_RALPH_LOOP_UPDATE: 'session:ralphLoopUpdate',
|
||||
SESSION_RALPH_TODO_UPDATE: 'session:ralphTodoUpdate',
|
||||
SESSION_RALPH_COMPLETION_DETECTED: 'session:ralphCompletionDetected',
|
||||
SESSION_RALPH_STATUS_UPDATE: 'session:ralphStatusUpdate',
|
||||
SESSION_CIRCUIT_BREAKER_UPDATE: 'session:circuitBreakerUpdate',
|
||||
SESSION_EXIT_GATE_MET: 'session:exitGateMet',
|
||||
|
||||
// Bash tools
|
||||
SESSION_BASH_TOOL_START: 'session:bashToolStart',
|
||||
SESSION_BASH_TOOL_END: 'session:bashToolEnd',
|
||||
SESSION_BASH_TOOLS_UPDATE: 'session:bashToolsUpdate',
|
||||
|
||||
// Hooks (Claude Code hook events)
|
||||
HOOK_IDLE_PROMPT: 'hook:idle_prompt',
|
||||
HOOK_PERMISSION_PROMPT: 'hook:permission_prompt',
|
||||
HOOK_ELICITATION_DIALOG: 'hook:elicitation_dialog',
|
||||
HOOK_STOP: 'hook:stop',
|
||||
HOOK_TEAMMATE_IDLE: 'hook:teammate_idle',
|
||||
HOOK_TASK_COMPLETED: 'hook:task_completed',
|
||||
|
||||
// Subagents (Claude Code background agents)
|
||||
SUBAGENT_DISCOVERED: 'subagent:discovered',
|
||||
SUBAGENT_UPDATED: 'subagent:updated',
|
||||
SUBAGENT_TOOL_CALL: 'subagent:tool_call',
|
||||
SUBAGENT_PROGRESS: 'subagent:progress',
|
||||
SUBAGENT_MESSAGE: 'subagent:message',
|
||||
SUBAGENT_TOOL_RESULT: 'subagent:tool_result',
|
||||
SUBAGENT_COMPLETED: 'subagent:completed',
|
||||
|
||||
// Images
|
||||
IMAGE_DETECTED: 'image:detected',
|
||||
|
||||
// Tunnel
|
||||
TUNNEL_STARTED: 'tunnel:started',
|
||||
TUNNEL_STOPPED: 'tunnel:stopped',
|
||||
TUNNEL_PROGRESS: 'tunnel:progress',
|
||||
TUNNEL_ERROR: 'tunnel:error',
|
||||
TUNNEL_QR_ROTATED: 'tunnel:qrRotated',
|
||||
TUNNEL_QR_REGENERATED: 'tunnel:qrRegenerated',
|
||||
TUNNEL_QR_AUTH_USED: 'tunnel:qrAuthUsed',
|
||||
|
||||
// Plan orchestration
|
||||
PLAN_SUBAGENT: 'plan:subagent',
|
||||
PLAN_PROGRESS: 'plan:progress',
|
||||
PLAN_STARTED: 'plan:started',
|
||||
PLAN_CANCELLED: 'plan:cancelled',
|
||||
PLAN_COMPLETED: 'plan:completed',
|
||||
};
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
// Utility Functions
|
||||
// ============================================================================
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
|
||||
/**
|
||||
* Get unified coordinates from mouse or touch event.
|
||||
|
||||
+14
-10
@@ -20,7 +20,7 @@
|
||||
<script defer src="vendor/xterm-addon-fit.min.js"></script>
|
||||
<script defer src="vendor/xterm-addon-webgl.min.js"></script>
|
||||
<script defer src="vendor/xterm-addon-unicode11.min.js"></script>
|
||||
<script defer src="vendor/xterm-zerolag-input.js?v=0.2.9"></script>
|
||||
<script defer src="vendor/xterm-zerolag-input.js?v=0.3.0"></script>
|
||||
<!-- Synchronous mobile detection — runs before first paint to prevent panel flash -->
|
||||
<script>if(window.innerWidth<768||(('ontouchstart' in window||navigator.maxTouchPoints>0)&&window.innerWidth<1024))document.documentElement.classList.add('mobile-init');</script>
|
||||
<!-- Inline critical CSS for instant skeleton paint (before styles.css loads) -->
|
||||
@@ -961,6 +961,10 @@
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
<div class="settings-item" id="tunnelUploadUrlRow" style="display:none">
|
||||
<span class="settings-item-label">Upload URL</span>
|
||||
<span id="tunnelUploadUrlDisplay" class="settings-item-value" style="cursor:pointer; text-decoration:underline; font-family:monospace; font-size:12px" title="Click to copy"></span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@@ -1670,14 +1674,14 @@
|
||||
<!-- Lines drawn dynamically -->
|
||||
</svg>
|
||||
|
||||
<script defer src="constants.js?v=0.2.9"></script>
|
||||
<script defer src="mobile-handlers.js?v=0.2.9"></script>
|
||||
<script defer src="voice-input.js?v=0.2.9"></script>
|
||||
<script defer src="notification-manager.js?v=0.2.9"></script>
|
||||
<script defer src="keyboard-accessory.js?v=0.2.9"></script>
|
||||
<script defer src="app.js?v=0.2.9"></script>
|
||||
<script defer src="ralph-wizard.js?v=0.2.9"></script>
|
||||
<script defer src="api-client.js?v=0.2.9"></script>
|
||||
<script defer src="subagent-windows.js?v=0.2.9"></script>
|
||||
<script defer src="constants.js?v=0.3.0"></script>
|
||||
<script defer src="mobile-handlers.js?v=0.3.0"></script>
|
||||
<script defer src="voice-input.js?v=0.3.0"></script>
|
||||
<script defer src="notification-manager.js?v=0.3.0"></script>
|
||||
<script defer src="keyboard-accessory.js?v=0.3.0"></script>
|
||||
<script defer src="app.js?v=0.3.0"></script>
|
||||
<script defer src="ralph-wizard.js?v=0.3.0"></script>
|
||||
<script defer src="api-client.js?v=0.3.0"></script>
|
||||
<script defer src="subagent-windows.js?v=0.3.0"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,9 +1,32 @@
|
||||
/**
|
||||
* @fileoverview Mobile keyboard accessory bar and modal focus trap.
|
||||
*
|
||||
* Defines two exports:
|
||||
*
|
||||
* - KeyboardAccessoryBar (singleton object) — Quick action buttons shown above the virtual
|
||||
* keyboard on mobile: arrow up/down, /init, /clear, /compact, paste, and dismiss.
|
||||
* Destructive actions (/clear, /compact) require double-tap confirmation (2s amber state).
|
||||
* Commands are sent as text + Enter separately for Ink compatibility.
|
||||
* Only initializes on touch devices (MobileDetection.isTouchDevice guard).
|
||||
*
|
||||
* - FocusTrap (class) — Traps Tab/Shift+Tab keyboard focus within a modal element.
|
||||
* Saves and restores previously focused element on deactivate. Used by Ralph wizard
|
||||
* and other modal dialogs.
|
||||
*
|
||||
* @globals {object} KeyboardAccessoryBar
|
||||
* @globals {class} FocusTrap
|
||||
*
|
||||
* @dependency mobile-handlers.js (MobileDetection.isTouchDevice)
|
||||
* @dependency app.js (uses global `app` for sendInput, activeSessionId, terminal)
|
||||
* @loadorder 5 of 9 — loaded after notification-manager.js, before app.js
|
||||
*/
|
||||
|
||||
// Codeman — Keyboard accessory bar and focus trap for modals
|
||||
// Loaded after mobile-handlers.js, before app.js
|
||||
|
||||
// ============================================================================
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
// Mobile Keyboard Accessory Bar
|
||||
// ============================================================================
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
|
||||
/**
|
||||
* KeyboardAccessoryBar - Quick action buttons shown above keyboard when typing.
|
||||
@@ -209,9 +232,9 @@ const KeyboardAccessoryBar = {
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
// Accessibility: Focus Trap for Modals
|
||||
// ============================================================================
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
|
||||
/**
|
||||
* FocusTrap - Traps keyboard focus within an element (typically a modal).
|
||||
|
||||
@@ -1,9 +1,33 @@
|
||||
/**
|
||||
* @fileoverview Mobile device support: detection, keyboard handling, and swipe navigation.
|
||||
*
|
||||
* Defines three singleton objects that manage mobile-specific behavior:
|
||||
*
|
||||
* - MobileDetection — Device type detection (mobile/tablet/desktop), touch capability,
|
||||
* iOS/Safari identification, and body class management for CSS targeting.
|
||||
* - KeyboardHandler — Virtual keyboard show/hide detection via visualViewport API,
|
||||
* toolbar/accessory bar repositioning, terminal resize on keyboard open/close,
|
||||
* and input scroll-into-view. Uses 100px threshold for iOS address bar drift.
|
||||
* - SwipeHandler — Horizontal swipe detection on the terminal area for session switching.
|
||||
* 80px minimum distance, 300ms maximum time, 100px max vertical drift.
|
||||
*
|
||||
* All three have init()/cleanup() lifecycle methods. They are re-initialized after SSE
|
||||
* reconnect (in handleInit) to prevent stale closures.
|
||||
*
|
||||
* @globals {object} MobileDetection
|
||||
* @globals {object} KeyboardHandler
|
||||
* @globals {object} SwipeHandler
|
||||
*
|
||||
* @dependency keyboard-accessory.js (KeyboardAccessoryBar reference in KeyboardHandler.onKeyboardShow, soft — guarded with typeof check)
|
||||
* @loadorder 2 of 9 — loaded after constants.js, before voice-input.js
|
||||
*/
|
||||
|
||||
// Codeman — Mobile detection, keyboard handling, and swipe navigation
|
||||
// Loaded after constants.js, before app.js
|
||||
|
||||
// ============================================================================
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
// Mobile Detection
|
||||
// ============================================================================
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
|
||||
/**
|
||||
* MobileDetection - Detects device type and touch capability.
|
||||
@@ -109,9 +133,9 @@ const MobileDetection = {
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
// Mobile Keyboard Handler
|
||||
// ============================================================================
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
|
||||
/**
|
||||
* KeyboardHandler - Simple handler to scroll inputs into view when keyboard appears.
|
||||
@@ -387,9 +411,9 @@ const KeyboardHandler = {
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
// Mobile Swipe Handler
|
||||
// ============================================================================
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
|
||||
/**
|
||||
* SwipeHandler - Detects horizontal swipes on terminal to switch sessions.
|
||||
|
||||
@@ -1,3 +1,30 @@
|
||||
/**
|
||||
* @fileoverview Five-layer notification system for session events and alerts.
|
||||
*
|
||||
* The NotificationManager class implements five notification layers:
|
||||
* 1. In-app notification drawer (slide-out panel with grouped notifications)
|
||||
* 2. Tab title flash (alternating "(*) Codeman" when tab is hidden)
|
||||
* 3. Browser Notification API (desktop push with auto-close after 8s)
|
||||
* 4. Web Push via service worker (OS-level notifications when tab is closed)
|
||||
* 5. Audio alerts (Web Audio API beep, user-opt-in)
|
||||
*
|
||||
* Features:
|
||||
* - Per-event-type preferences (enabled, browser, audio, push) with v1→v4 migration
|
||||
* - Device-specific defaults (notifications disabled on mobile by default)
|
||||
* - 5s notification grouping window to batch rapid-fire events
|
||||
* - 100-notification cap with oldest eviction
|
||||
* - Rate limiting: 3s between browser notifications
|
||||
* - Visibility tracking (pauses title flash when tab becomes visible)
|
||||
* - iOS Safari bfcache support via pageshow event
|
||||
*
|
||||
* @class NotificationManager
|
||||
* @param {CodemanApp} app - Reference to the main app instance
|
||||
*
|
||||
* @dependency constants.js (STUCK_THRESHOLD_DEFAULT_MS, timing constants)
|
||||
* @dependency mobile-handlers.js (MobileDetection.getDeviceType for device-specific defaults)
|
||||
* @loadorder 4 of 9 — loaded after voice-input.js, before keyboard-accessory.js
|
||||
*/
|
||||
|
||||
// Codeman — Multi-layer notification system
|
||||
// Loaded after mobile-handlers.js, before app.js
|
||||
|
||||
|
||||
@@ -1,10 +1,30 @@
|
||||
/**
|
||||
* Ralph Loop Wizard — extracted from app.js for maintainability.
|
||||
* Extends CodemanApp.prototype with wizard methods.
|
||||
* Loaded after app.js in index.html.
|
||||
* @fileoverview Ralph Loop Wizard — multi-step modal for configuring autonomous task loops.
|
||||
*
|
||||
* Extends CodemanApp.prototype with wizard methods for the Ralph Loop setup flow:
|
||||
* Step 1: Task description, completion phrase, iteration limit, case selection
|
||||
* Step 2: AI-powered plan generation (optional) with research agent → planner agent pipeline
|
||||
* Step 3: Respawn configuration (idle timeout, kickstart prompt, auto-clear/init)
|
||||
* Step 4: Review and launch
|
||||
*
|
||||
* Features:
|
||||
* - Plan generation via POST /api/sessions/:id/plan/generate with SSE progress streaming
|
||||
* - Existing @fix_plan.md detection and reuse
|
||||
* - Plan detail level selection (brief/detailed/comprehensive)
|
||||
* - Case selector population from /api/cases
|
||||
* - Focus trap for modal accessibility
|
||||
* - Abort controller for cancelling in-flight plan generation
|
||||
*
|
||||
* @mixin Extends CodemanApp.prototype via Object.assign
|
||||
* @dependency app.js (CodemanApp class must be defined)
|
||||
* @dependency keyboard-accessory.js (FocusTrap class for modal focus management)
|
||||
* @dependency constants.js (escapeHtml)
|
||||
* @loadorder 7 of 9 — loaded after app.js, before api-client.js
|
||||
*/
|
||||
|
||||
// ========== Ralph Loop Wizard ==========
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
// Ralph Loop Wizard
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
|
||||
Object.assign(CodemanApp.prototype, {
|
||||
|
||||
@@ -388,7 +408,9 @@ Object.assign(CodemanApp.prototype, {
|
||||
}
|
||||
},
|
||||
|
||||
// ========== Plan Generation ==========
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
// Plan Generation
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
|
||||
resetPlanGenerationUI() {
|
||||
// Hide all plan generation states
|
||||
@@ -780,7 +802,9 @@ Object.assign(CodemanApp.prototype, {
|
||||
this.closePlanSubagentWindows();
|
||||
},
|
||||
|
||||
// ========== Plan Subagent Windows ==========
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
// Plan Subagent Windows
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
|
||||
handlePlanSubagentEvent(event) {
|
||||
if (this.planGenerationStopped) return;
|
||||
|
||||
@@ -1,3 +1,23 @@
|
||||
/**
|
||||
* @fileoverview Subagent floating window management mixed into CodemanApp.prototype.
|
||||
*
|
||||
* Extends CodemanApp with methods for managing floating terminal windows that display
|
||||
* Claude Code background agent (subagent) output. Each subagent window has its own
|
||||
* xterm.js terminal instance, drag/resize handles, minimize/close controls, and
|
||||
* connection lines drawn to the parent session tab.
|
||||
*
|
||||
* Key functionality:
|
||||
* - Tab badge dropdown showing minimized agents per session
|
||||
* - Minimize/restore/permanently-close lifecycle for subagent windows
|
||||
* - Cross-browser state persistence (localStorage + server-backed PUT /api/subagent-window-states)
|
||||
* - Window state saved on every minimize/restore/close action
|
||||
*
|
||||
* @mixin Extends CodemanApp.prototype via Object.assign
|
||||
* @dependency app.js (CodemanApp class, this.subagents, this.subagentWindows, this.minimizedSubagents)
|
||||
* @dependency constants.js (escapeHtml)
|
||||
* @loadorder 9 of 9 — loaded last, after api-client.js
|
||||
*/
|
||||
|
||||
// Codeman — Subagent window management for CodemanApp
|
||||
// Loaded after app.js (needs CodemanApp class defined)
|
||||
|
||||
@@ -80,7 +100,9 @@ Object.assign(CodemanApp.prototype, {
|
||||
this.saveSubagentWindowStates();
|
||||
},
|
||||
|
||||
// ========== Subagent Window State Persistence ==========
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
// Subagent Window State Persistence
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
|
||||
/**
|
||||
* Save subagent window states (minimized/open) to server for cross-browser persistence.
|
||||
@@ -198,7 +220,9 @@ Object.assign(CodemanApp.prototype, {
|
||||
});
|
||||
},
|
||||
|
||||
// ========== Subagent Connection Lines ==========
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
// Subagent Connection Lines
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
//
|
||||
// Connection lines are drawn from agent windows to their parent TABs.
|
||||
// The parent TAB is determined by the PERSISTENT subagentParentMap.
|
||||
@@ -434,7 +458,9 @@ Object.assign(CodemanApp.prototype, {
|
||||
}
|
||||
},
|
||||
|
||||
// ========== Subagent Floating Windows ==========
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
// Subagent Floating Windows
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
|
||||
openSubagentWindow(agentId) {
|
||||
// If window already exists, focus it
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/**
|
||||
* @fileoverview Service worker for Web Push notifications.
|
||||
*
|
||||
* Receives push events from the Codeman server (via web-push library) and displays
|
||||
* OS-level notifications. Handles notification clicks to focus an existing Codeman
|
||||
* tab or open a new one. Supports action buttons, per-session deep linking, and
|
||||
* critical notification persistence (requireInteraction).
|
||||
*
|
||||
* Lifecycle: skipWaiting on install, claim clients on activate — ensures the latest
|
||||
* service worker takes control immediately without waiting for tab refresh.
|
||||
*
|
||||
* @dependency None (runs in ServiceWorkerGlobalScope, isolated from page scripts)
|
||||
* @see src/push-store.ts — server-side VAPID key management and subscription CRUD
|
||||
*/
|
||||
|
||||
// Codeman Service Worker — Web Push notifications
|
||||
// This service worker receives push events from the server and displays OS-level notifications.
|
||||
// It also handles notification clicks to focus or open the Codeman tab.
|
||||
|
||||
@@ -1,9 +1,33 @@
|
||||
/**
|
||||
* @fileoverview Voice input with Deepgram Nova-3 (primary) and Web Speech API (fallback).
|
||||
*
|
||||
* Defines two singleton objects:
|
||||
*
|
||||
* - DeepgramProvider — Direct browser-to-Deepgram WebSocket connection for speech-to-text.
|
||||
* Captures audio via MediaRecorder, streams chunks every 250ms, handles KeepAlive pings,
|
||||
* auto-detects MIME type (opus/webm/mp4), and supports custom key terms for dev vocabulary.
|
||||
*
|
||||
* - VoiceInput — High-level voice input controller. Toggle mode: tap mic to start, tap
|
||||
* again to stop. Auto-stops after 3s silence. Shows floating preview overlay with recording
|
||||
* indicator, level meter (AnalyserNode), and elapsed timer. Two insert modes: "direct"
|
||||
* (inject into local echo overlay or PTY) and "compose" (editable textarea overlay).
|
||||
* Includes a temporary green Send button that replaces the settings gear icon after voice input.
|
||||
* Web Speech API has auto-retry (up to 2x) for premature onend and iOS Safari stability check.
|
||||
*
|
||||
* @globals {object} DeepgramProvider
|
||||
* @globals {object} VoiceInput
|
||||
*
|
||||
* @dependency mobile-handlers.js (MobileDetection for device checks)
|
||||
* @dependency app.js (uses global `app` for sendInput, showToast, terminal focus)
|
||||
* @loadorder 3 of 9 — loaded after mobile-handlers.js, before notification-manager.js
|
||||
*/
|
||||
|
||||
// Codeman — Voice input with Deepgram Nova-3 and Web Speech API fallback
|
||||
// Loaded after mobile-handlers.js, before app.js
|
||||
|
||||
// ============================================================================
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
// Voice Input (Deepgram Nova-3 + Web Speech API fallback)
|
||||
// ============================================================================
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
|
||||
/**
|
||||
* DeepgramProvider - Speech-to-text via Deepgram Nova-3 WebSocket API.
|
||||
|
||||
Reference in New Issue
Block a user