visual-journal / scripts /smoke-hf-space-memory.mjs
gpt-image-playground deploy
Deploy 6590d91 to Docker Space
ecb6084
Raw
History Blame Contribute Delete
4.98 kB
#!/usr/bin/env node
import { spawnSync } from 'node:child_process';
import { readPositiveIntegerEnv } from './env-utils.mjs';
const imageName = process.env.HF_SPACE_SMOKE_IMAGE || 'gpt-image-playground:hf-space-memory-smoke';
const containerName = process.env.HF_SPACE_SMOKE_CONTAINER || 'gpt-image-playground-hf-space-smoke';
const parsedHostPort = readPositiveIntegerEnv('HF_SPACE_SMOKE_PORT', 4785);
if (parsedHostPort > 65_535) {
throw new Error('HF_SPACE_SMOKE_PORT must be less than or equal to 65535');
}
const hostPort = String(parsedHostPort);
const token = process.env.HF_SPACE_SMOKE_AGENT_TOKEN || 'hf-space-smoke-token';
const baseUrl = `http://127.0.0.1:${hostPort}`;
const readyTimeoutMs = readPositiveIntegerEnv('HF_SPACE_SMOKE_READY_TIMEOUT_MS', 45_000);
function run(command, args, options = {}) {
const result = spawnSync(command, args, {
stdio: options.capture ? 'pipe' : 'inherit',
encoding: 'utf8',
env: { ...process.env, ...(options.env || {}) }
});
if (result.error) {
throw new Error(`${command} ${args.join(' ')} failed to start: ${result.error.message}`);
}
if (result.status !== 0) {
const output = [result.stdout, result.stderr].filter(Boolean).join('\n').trim();
throw new Error(`${command} ${args.join(' ')} failed${output ? `\n${output}` : ''}`);
}
return result.stdout || '';
}
async function fetchJson(path, options = {}) {
const response = await fetch(`${baseUrl}${path}`, options);
const text = await response.text();
let body;
try {
body = JSON.parse(text);
} catch {
throw new Error(`${path} returned non-JSON response: ${text.slice(0, 200)}`);
}
if (!response.ok) {
throw new Error(`${path} failed with ${response.status}: ${JSON.stringify(body)}`);
}
return body;
}
async function waitForReady() {
const deadline = Date.now() + readyTimeoutMs;
let lastError;
while (Date.now() < deadline) {
try {
const response = await fetch(baseUrl, {
headers: {
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 Mobile/15E148'
}
});
if (response.ok) return;
lastError = new Error(`HTTP ${response.status}`);
} catch (error) {
lastError = error;
}
await new Promise((resolve) => setTimeout(resolve, 1000));
}
throw lastError || new Error('container did not become ready');
}
function cleanup() {
spawnSync('docker', ['rm', '-f', containerName], { stdio: 'ignore' });
}
function assertEqual(actual, expected, label) {
if (actual !== expected) {
throw new Error(`${label}: expected ${expected}, got ${actual}`);
}
}
function assertJsonEqual(actual, expected, label) {
const actualJson = JSON.stringify(actual);
const expectedJson = JSON.stringify(expected);
if (actualJson !== expectedJson) {
throw new Error(`${label}: expected ${expectedJson}, got ${actualJson}`);
}
}
cleanup();
try {
run('docker', [
'build',
'--build-arg',
'NEXT_PUBLIC_IMAGE_STORAGE_MODE=indexeddb',
'-t',
imageName,
'.'
]);
run('docker', [
'run',
'-d',
'--name',
containerName,
'-p',
`127.0.0.1:${hostPort}:4783`,
'-e',
'AGENT_STATE_BACKEND=memory',
'-e',
'AGENT_SQLITE_PATH=',
'-e',
'AGENT_DATABASE_URL=',
'-e',
'AGENT_DB_PASSWORD=',
'-e',
'AGENT_DB_PASSWORD_FILE=',
'-e',
'NEXT_PUBLIC_IMAGE_STORAGE_MODE=indexeddb',
'-e',
'APP_LOG_LEVEL=warn',
'-e',
`AGENT_API_TOKEN=${token}`,
imageName
]);
await waitForReady();
const capabilities = await fetchJson('/api/agent/capabilities');
assertEqual(capabilities.auth?.required, true, 'Agent auth required flag');
assertJsonEqual(capabilities.auth?.schemes, ['bearer'], 'Agent auth schemes');
assertEqual(capabilities.defaults?.state_backend, 'memory', 'Agent state backend');
assertEqual(capabilities.storage?.image_storage_mode, 'indexeddb', 'Image storage mode');
assertEqual(capabilities.storage?.postgres_configured, false, 'PostgreSQL configured flag');
const runtime = await fetchJson('/api/runtime-capabilities');
assertEqual(typeof runtime.streamingBatch?.enabled, 'boolean', 'Runtime capabilities shape');
run('node', ['skills/gpt-image-playground-agent/scripts/generate-image.mjs'], {
env: {
GPT_IMAGE_PLAYGROUND_URL: baseUrl,
GPT_IMAGE_AGENT_TOKEN: token,
GPT_IMAGE_AGENT_CONTRACT_CHECK: '1'
}
});
run('node', ['skills/gpt-image-playground-agent/scripts/edit-image.mjs'], {
env: {
GPT_IMAGE_PLAYGROUND_URL: baseUrl,
GPT_IMAGE_AGENT_TOKEN: token,
GPT_IMAGE_AGENT_CONTRACT_CHECK: '1'
}
});
console.log(
JSON.stringify(
{
ok: true,
baseUrl,
state_backend: capabilities.defaults.state_backend,
image_storage_mode: capabilities.storage.image_storage_mode,
agent_contract_check: true
},
null,
2
)
);
} finally {
cleanup();
}