mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-06 07:29:42 +02:00
Merge master into PR #156 (remote tmux durability)
Resolutions: - session.ts: keep the extracted _buildRespawnPaneOptions() helper (COD-108) and add master's docker/owner fields to it - tmux-manager.ts: docker branch first, then remote via buildRemoteSessionCommand (now an options object threading claudeMode/allowedTools into buildRemoteLaunchCommand, preserving the 6.3 multi-user permission downgrade) - case-routes.ts: keep master's adminOnly helper; gate the new COD-105 discovery endpoint admin-only in multi-user mode (hosts are machine-level infra) - settings-ui.js: union of remoteAutoReconnect + master's header-button defaults - session-routes.ts: union of imports; session gets remote + owner Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+143
-4
@@ -118,12 +118,13 @@
|
||||
</div>
|
||||
<button class="btn-icon-header btn-redraw-terminal btn-redraw-terminal--hidden" onclick="app.restoreTerminalSize()" title="Redraw terminal to fit current screen (Ctrl+Shift+R)" aria-label="Redraw terminal"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="1 4 1 10 7 10"/><polyline points="23 20 23 14 17 14"/><path d="M20.49 9A9 9 0 0 0 5.64 5.64L1 10m22 4l-4.64 4.36A9 9 0 0 1 3.51 15"/></svg></button>
|
||||
<button class="btn-icon-header btn-response-viewer-header btn-response-viewer-header--hidden" onclick="app.toggleResponseViewer()" title="View last response" aria-label="View last response"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg></button>
|
||||
<button class="btn-icon-header btn-away-digest" onclick="app.openAwayDigest()" title="Away Digest" aria-label="Open away digest"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M8 6h13"/><path d="M8 12h13"/><path d="M8 18h13"/><path d="M3 6h.01"/><path d="M3 12h.01"/><path d="M3 18h.01"/></svg></button>
|
||||
<button class="btn-icon-header btn-session-manager" onclick="app.openSessionManager()" title="Session Manager" aria-label="Open session manager"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="12 2 2 7 12 12 22 7 12 2"/><polyline points="2 17 12 22 22 17"/><polyline points="2 12 12 17 22 12"/></svg></button>
|
||||
<button class="btn-icon-header btn-away-digest btn-away-digest--hidden" onclick="app.openAwayDigest()" title="Away Digest" aria-label="Open away digest"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M8 6h13"/><path d="M8 12h13"/><path d="M8 18h13"/><path d="M3 6h.01"/><path d="M3 12h.01"/><path d="M3 18h.01"/></svg></button>
|
||||
<button class="btn-icon-header btn-session-manager btn-session-manager--hidden" onclick="app.openSessionManager()" title="Session Manager" aria-label="Open session manager"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="12 2 2 7 12 12 22 7 12 2"/><polyline points="2 17 12 22 22 17"/><polyline points="2 12 12 17 22 12"/></svg></button>
|
||||
<button class="btn-icon-header btn-attachments-history btn-attachments-history--hidden" id="attachmentsHistoryBtn" onclick="app.toggleAttachmentHistory()" title="Attachments" aria-label="Open attachment history" aria-expanded="false">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"/></svg>
|
||||
<span class="attachment-history-badge" id="attachmentHistoryBadge" style="display:none;">0</span>
|
||||
</button>
|
||||
<button class="btn-icon-header btn-file-viewer btn-file-viewer--hidden" onclick="app.toggleFileBrowserButton()" title="File Viewer" aria-label="Open file viewer" aria-expanded="false"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/></svg></button>
|
||||
<button class="btn-icon-header btn-multimonitor btn-multimonitor--hidden" onclick="app.launchMultiMonitor()" title="Open Codeman across all displays" aria-label="Open Codeman across all displays"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="2" y="4" width="13" height="9" rx="1.5"/><rect x="11" y="9" width="11" height="8" rx="1.5"/></svg></button>
|
||||
<button class="btn-icon-header btn-ultracode-agents btn-ultracode-agents--hidden" onclick="app.toggleUltracodeAgentsPanel()" title="Ultracode / Workflow agents" aria-label="Open ultracode workflow agents"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="6" cy="6" r="2.5"/><circle cx="6" cy="18" r="2.5"/><circle cx="18" cy="12" r="2.5"/><path d="M8.2 7.2 15.6 11M8.2 16.8 15.6 13"/></svg></button>
|
||||
<div class="header-plan-usage header-plan-usage--hidden" id="planUsageChip" title="Claude plan usage limits">—</div>
|
||||
@@ -557,7 +558,7 @@
|
||||
<div class="toolbar-right">
|
||||
<!-- Orchestrator button hidden until feature is ready -->
|
||||
<!-- <button class="btn-toolbar btn-sm" onclick="app.toggleOrchestratorPanel()" title="Orchestrator Loop">⚙ Orchestrator</button> -->
|
||||
<button class="btn-toolbar btn-sm" onclick="app.openCron()" title="Cron Jobs">⏰ Cron</button>
|
||||
<button class="btn-toolbar btn-sm btn-cron" onclick="app.openCron()" title="Cron Jobs">⏰ Cron</button>
|
||||
<span class="version-display" id="versionDisplay" title="Codeman version">v0.0.0</span>
|
||||
</div>
|
||||
</footer>
|
||||
@@ -1268,6 +1269,13 @@
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="settings-item" title="Show the file viewer button in header (opens the file browser panel for the active session)">
|
||||
<span class="settings-item-label">File Viewer</span>
|
||||
<label class="switch switch-sm">
|
||||
<input type="checkbox" id="appSettingsShowFileViewerButton">
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="settings-item" title="Show the attachments button in header (opens the attachment history drawer)">
|
||||
<span class="settings-item-label">Attachments Button</span>
|
||||
<label class="switch switch-sm">
|
||||
@@ -1282,6 +1290,27 @@
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="settings-item" title="Show the session manager button in the header (opens the session manager — sessions also stay reachable via the Ctrl+K palette)">
|
||||
<span class="settings-item-label">Session Manager Button</span>
|
||||
<label class="switch switch-sm">
|
||||
<input type="checkbox" id="appSettingsShowSessionButton">
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="settings-item" title="Show the away digest button in the header (opens the 'what happened while you were away' summary)">
|
||||
<span class="settings-item-label">Away Digest Button</span>
|
||||
<label class="switch switch-sm">
|
||||
<input type="checkbox" id="appSettingsShowAwayDigestButton">
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="settings-item" title="Show the Cron button in the footer toolbar (opens the cron jobs manager)">
|
||||
<span class="settings-item-label">Cron Button</span>
|
||||
<label class="switch switch-sm">
|
||||
<input type="checkbox" id="appSettingsShowCronButton">
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="settings-item" title="Show a terminal redraw button in the header — refit the terminal to the current screen size (useful when switching between devices)">
|
||||
<span class="settings-item-label">Redraw Terminal Button</span>
|
||||
<label class="switch switch-sm">
|
||||
@@ -1420,10 +1449,11 @@
|
||||
<label>Startup Mode</label>
|
||||
<select id="appSettingsClaudeMode" class="form-select">
|
||||
<option value="dangerously-skip-permissions">Skip Permissions (default)</option>
|
||||
<option value="auto">Auto (classifier-guarded, low prompts)</option>
|
||||
<option value="normal">Normal (with prompts)</option>
|
||||
<option value="allowedTools">Allowed Tools Only</option>
|
||||
</select>
|
||||
<span class="form-hint">How Claude CLI is started in screen sessions</span>
|
||||
<span class="form-hint">How Claude CLI is started in screen sessions. Auto Mode runs without routine prompts behind a background safety classifier (needs Claude Code 2.1.207+ and Opus 4.6+/Sonnet 4.6+/Fable 5)</span>
|
||||
</div>
|
||||
<div class="form-row" id="allowedToolsRow" style="display: none;">
|
||||
<label>Allowed Tools</label>
|
||||
@@ -1836,6 +1866,7 @@
|
||||
<button class="modal-tab-btn active" data-tab="case-create">Create New</button>
|
||||
<button class="modal-tab-btn" data-tab="case-link">Link Existing</button>
|
||||
<button class="modal-tab-btn" data-tab="case-remote">Remote</button>
|
||||
<button class="modal-tab-btn" data-tab="case-docker">Docker</button>
|
||||
<button class="modal-tab-btn" data-tab="case-manage">Manage</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
@@ -1850,6 +1881,53 @@
|
||||
<label>Description (optional)</label>
|
||||
<input type="text" id="newCaseDescription" placeholder="A brief description..." autocomplete="off">
|
||||
</div>
|
||||
<div class="form-row docker-quick-row">
|
||||
<label class="checkbox-row"><input type="checkbox" id="newCaseDocker"> 🐳 Run in an isolated Docker container</label>
|
||||
<span class="form-hint">Runs this case in a hardened, isolated container. The base image is built automatically on first use. Docker/Podman must be installed.</span>
|
||||
</div>
|
||||
<details class="advanced-options docker-quick-settings" id="dockerQuickSettings">
|
||||
<summary>Container settings (optional, sensible defaults)</summary>
|
||||
<div class="advanced-options-content">
|
||||
<div class="form-row">
|
||||
<label>Template</label>
|
||||
<select id="quickDockerTemplate" onchange="app.applyDockerTemplate()">
|
||||
<option value="small">Small — 2 GB RAM, 1 CPU</option>
|
||||
<option value="medium" selected>Medium — 4 GB RAM, 2 CPU (default)</option>
|
||||
<option value="large">Large — 8 GB RAM, 4 CPU</option>
|
||||
<option value="gpu">GPU — 8 GB RAM, 4 CPU, all GPUs</option>
|
||||
<option value="custom">Custom</option>
|
||||
</select>
|
||||
<span class="form-hint">Disk is elastic: storage grows automatically as data flows in (no fixed cap).</span>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label>Memory</label>
|
||||
<input type="text" id="quickDockerMemory" placeholder="4g" autocomplete="off" spellcheck="false">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label>CPUs</label>
|
||||
<input type="text" id="quickDockerCpus" placeholder="2" autocomplete="off" spellcheck="false">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label>GPUs</label>
|
||||
<input type="text" id="quickDockerGpus" placeholder="none (e.g. all, or 1)" autocomplete="off" spellcheck="false">
|
||||
<span class="form-hint">Needs the NVIDIA container toolkit on the host.</span>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label>Network</label>
|
||||
<select id="quickDockerNetwork">
|
||||
<option value="bridge">bridge (internet on)</option>
|
||||
<option value="none">none (fully isolated)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label>Image</label>
|
||||
<input type="text" id="quickDockerImage" placeholder="codeman/agent:base" autocomplete="off" spellcheck="false">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label class="checkbox-row"><input type="checkbox" id="quickDockerMountCreds" checked> Mount host credentials (~/.claude etc.)</label>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
<!-- Link Existing Tab -->
|
||||
<div class="modal-tab-content hidden" id="case-link">
|
||||
@@ -1935,12 +2013,72 @@
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
<!-- Docker Tab -->
|
||||
<div class="modal-tab-content hidden" id="case-docker">
|
||||
<div class="form-row">
|
||||
<label>Case Name</label>
|
||||
<input type="text" id="dockerCaseName" placeholder="sandbox" pattern="[a-zA-Z0-9_-]+" autocomplete="off" autocapitalize="off" spellcheck="false">
|
||||
<span class="form-hint">Runs inside an isolated container. Multiple sessions can share the same container.</span>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label>Workspace Path</label>
|
||||
<input type="text" id="dockerWorkspacePath" placeholder="/home/user/projects/sandbox" autocomplete="off" autocapitalize="off" autocorrect="off" spellcheck="false">
|
||||
<span class="form-hint">Absolute HOST directory, bind-mounted into the container. Codeman scaffolds CLAUDE.md + hooks into it.</span>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label>Host ID</label>
|
||||
<input type="text" id="dockerHostId" placeholder="local" pattern="[a-zA-Z0-9_-]+" autocomplete="off" autocapitalize="off" spellcheck="false">
|
||||
<span class="form-hint">A reusable docker host profile. Reuse the same ID across cases to share settings.</span>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label>Image</label>
|
||||
<input type="text" id="dockerImage" placeholder="codeman/agent:base" autocomplete="off" autocapitalize="off" spellcheck="false">
|
||||
<span class="form-hint">Build it once with <code>node scripts/build-agent-image.mjs</code>. Contains node + claude/codex/gemini + tmux.</span>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label>Network</label>
|
||||
<select id="dockerNetwork">
|
||||
<option value="bridge">bridge (internet on, default)</option>
|
||||
<option value="none">none (fully isolated, no network)</option>
|
||||
<option value="custom">custom bridge</option>
|
||||
</select>
|
||||
</div>
|
||||
<details class="advanced-options">
|
||||
<summary>Advanced container settings</summary>
|
||||
<div class="advanced-options-content">
|
||||
<div class="form-row">
|
||||
<label>Memory</label>
|
||||
<input type="text" id="dockerMemory" placeholder="4g" autocomplete="off" spellcheck="false">
|
||||
<span class="form-hint">Optional, e.g. 4g / 512m. Enforced as a hard OOM cap where the engine supports it.</span>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label>CPUs</label>
|
||||
<input type="text" id="dockerCpus" placeholder="2" autocomplete="off" spellcheck="false">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label class="checkbox-row"><input type="checkbox" id="dockerMountCredentials" checked> Mount host credentials (~/.claude etc.)</label>
|
||||
<span class="form-hint">On: your existing login just works (creds stay on the host, never in exports). Off: sealed sandbox, log in inside the container.</span>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label class="checkbox-row"><input type="checkbox" id="dockerResumeOnStart" checked> Resume last conversation on relaunch</label>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
<span class="form-hint" id="dockerLinkStatus" style="margin-top: 8px; display: block;"></span>
|
||||
</div>
|
||||
<!-- Manage Tab -->
|
||||
<div class="modal-tab-content hidden" id="case-manage">
|
||||
<div class="case-manage-list" id="caseManageList">
|
||||
<!-- Populated by JS -->
|
||||
</div>
|
||||
<span class="form-hint" style="margin-top: 8px; display: block;">Use arrows to reorder. Changes are saved automatically.</span>
|
||||
<div id="dockerExportsSection" style="margin-top: 16px; border-top: 1px solid var(--border, #333); padding-top: 12px;">
|
||||
<div style="display:flex; align-items:center; justify-content:space-between; margin-bottom:8px;">
|
||||
<strong style="font-size: 13px;">Docker exports</strong>
|
||||
<button class="btn-toolbar" onclick="app.refreshDockerExports()">Refresh</button>
|
||||
</div>
|
||||
<div class="case-manage-list" id="dockerExportsList"><span class="form-hint">No exports yet. Export a docker case from its tab.</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-actions">
|
||||
@@ -2376,6 +2514,7 @@
|
||||
<script defer src="settings-ui.js"></script>
|
||||
<script defer src="panels-ui.js"></script>
|
||||
<script defer src="ultracode-panel.js"></script>
|
||||
<script defer src="admin-ui.js"></script>
|
||||
<script defer src="session-ui.js"></script>
|
||||
<script defer src="ralph-wizard.js"></script>
|
||||
<script defer src="api-client.js"></script>
|
||||
|
||||
Reference in New Issue
Block a user