mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-06 23:49:41 +02:00
feat(docker): resource templates, GPU, elastic disk, bridge-hooks listener
- One-click "Run in Docker" gains an expandable settings panel with a Template picker (Small 2G/1 · Medium 4G/2 default · Large 8G/4 · GPU 8G/4/all) plus memory/cpu/gpu/network/image/mount-creds overrides. Any tweak creates a dedicated per-case host; the plain checkbox keeps using the shared `default` host. - GPU passthrough: `gpus` on DockerHost/SessionDocker -> `--gpus <value>` in create args (needs the NVIDIA container toolkit). Elastic disk: no `--storage-opt` cap, so container storage grows as data flows in. - CODEMAN_DOCKER_BRIDGE_HOOKS=1: opt-in second listener on the docker bridge gateway (auto-detected 172.17.0.1, override CODEMAN_DOCKER_BRIDGE_HOST) that serves ONLY the hook endpoints and delegates into the secret-gated pipeline, so in-container hooks fire on a loopback-only server. Non-hook paths -> 403; host-internal, not LAN. Verified live: Large template applies real 8GB/4CPU limits; a secret-authenticated hook POST from inside a container now reaches the handler (was connection-refused); non-hook paths return 403; template UI + GPU field verified via Playwright. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1642,16 +1642,19 @@ Object.assign(CodemanApp.prototype, {
|
||||
return;
|
||||
}
|
||||
|
||||
// One-click "Run in Docker": create the case folder AND a container (default
|
||||
// settings), then start a session inside it.
|
||||
// One-click "Run in Docker": create the case folder AND a container, then start
|
||||
// a session inside it. Optional expandable settings override the defaults.
|
||||
const inDocker = document.getElementById('newCaseDocker')?.checked;
|
||||
const endpoint = inDocker ? '/api/cases/docker-quickcreate' : '/api/cases';
|
||||
const payload = inDocker
|
||||
? { name, description, ...this._collectDockerQuickSettings() }
|
||||
: { name, description };
|
||||
|
||||
try {
|
||||
const res = await fetch(endpoint, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ name, description })
|
||||
body: JSON.stringify(payload)
|
||||
});
|
||||
|
||||
const data = await res.json();
|
||||
@@ -1678,6 +1681,54 @@ Object.assign(CodemanApp.prototype, {
|
||||
}
|
||||
},
|
||||
|
||||
// Show/hide the expandable container-settings section under the Docker checkbox.
|
||||
toggleDockerQuickSettings() {
|
||||
const on = document.getElementById('newCaseDocker')?.checked;
|
||||
const el = document.getElementById('dockerQuickSettings');
|
||||
if (el) el.style.display = on ? '' : 'none';
|
||||
},
|
||||
|
||||
// Fill the memory/cpu/gpu fields from a resource template. `medium` clears them so
|
||||
// the server uses its defaults (no per-case host); `custom` leaves them editable.
|
||||
applyDockerTemplate() {
|
||||
const t = document.getElementById('quickDockerTemplate')?.value;
|
||||
const presets = {
|
||||
small: { m: '2g', c: '1', g: '' },
|
||||
medium: { m: '', c: '', g: '' },
|
||||
large: { m: '8g', c: '4', g: '' },
|
||||
gpu: { m: '8g', c: '4', g: 'all' },
|
||||
};
|
||||
const p = presets[t];
|
||||
if (!p) return; // 'custom' — leave fields as-is
|
||||
const set = (id, v) => {
|
||||
const el = document.getElementById(id);
|
||||
if (el) el.value = v;
|
||||
};
|
||||
set('quickDockerMemory', p.m);
|
||||
set('quickDockerCpus', p.c);
|
||||
set('quickDockerGpus', p.g);
|
||||
},
|
||||
|
||||
// Collect only the non-default docker overrides (empty fields fall back to defaults
|
||||
// server-side; sent as undefined, never null, per the Zod .optional() gotcha).
|
||||
_collectDockerQuickSettings() {
|
||||
const val = (id) => (document.getElementById(id)?.value || '').trim();
|
||||
const o = {};
|
||||
const mem = val('quickDockerMemory');
|
||||
if (mem) o.memory = mem;
|
||||
const cpus = val('quickDockerCpus');
|
||||
if (cpus) o.cpus = cpus;
|
||||
const gpus = val('quickDockerGpus');
|
||||
if (gpus && gpus.toLowerCase() !== 'none') o.gpus = gpus;
|
||||
const net = document.getElementById('quickDockerNetwork')?.value;
|
||||
if (net && net !== 'bridge') o.network = net;
|
||||
const img = val('quickDockerImage');
|
||||
if (img) o.image = img;
|
||||
const mc = document.getElementById('quickDockerMountCreds');
|
||||
if (mc && !mc.checked) o.mountCredentials = false;
|
||||
return o;
|
||||
},
|
||||
|
||||
async linkCase() {
|
||||
const name = document.getElementById('linkCaseName').value.trim();
|
||||
const path = document.getElementById('linkCasePath').value.trim();
|
||||
|
||||
Reference in New Issue
Block a user