mirror of
https://github.com/dtzp555-max/ocm.git
synced 2026-07-19 09:43:37 +00:00
fix: Add Agent creates runtime dirs + SOUL.md personality support
- POST /api/agents/bot now creates agents/<id>/sessions/ runtime directory - POST /api/agents (sub-agent) also creates agents/<id>/sessions/ - Add Agent form now includes Purpose and Personality fields - Personality keywords generate structured SOUL.md, empty uses default growth prompt - Notes now remind to restart gateway for new bots Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+22
-6
@@ -369,7 +369,7 @@ async function handleApi(req, res, urlObj, body) {
|
|||||||
|
|
||||||
// POST /api/agents/bot — create agent with its own bot token
|
// POST /api/agents/bot — create agent with its own bot token
|
||||||
if (method === 'POST' && pathname === '/api/agents/bot') {
|
if (method === 'POST' && pathname === '/api/agents/bot') {
|
||||||
const { botToken, agentId, name, model, workspace } = body;
|
const { botToken, agentId, name, model, workspace, purpose, personality } = body;
|
||||||
if (!botToken || !botToken.trim()) {
|
if (!botToken || !botToken.trim()) {
|
||||||
res.writeHead(400); res.end(JSON.stringify({ error: 'Bot Token is required' })); return;
|
res.writeHead(400); res.end(JSON.stringify({ error: 'Bot Token is required' })); return;
|
||||||
}
|
}
|
||||||
@@ -425,16 +425,21 @@ async function handleApi(req, res, urlObj, body) {
|
|||||||
await fsp.mkdir(wsPath, { recursive: true });
|
await fsp.mkdir(wsPath, { recursive: true });
|
||||||
await fsp.mkdir(path.join(wsPath, 'memory'), { recursive: true });
|
await fsp.mkdir(path.join(wsPath, 'memory'), { recursive: true });
|
||||||
const agentName = name || agentId;
|
const agentName = name || agentId;
|
||||||
await fsp.writeFile(path.join(wsPath, 'SOUL.md'), generateSoulMd(agentName, '', ''), 'utf8');
|
await fsp.writeFile(path.join(wsPath, 'SOUL.md'), generateSoulMd(agentName, purpose || '', personality || ''), 'utf8');
|
||||||
await fsp.writeFile(path.join(wsPath, 'MEMORY.md'), generateMemoryMd(agentName, ''), 'utf8');
|
await fsp.writeFile(path.join(wsPath, 'MEMORY.md'), generateMemoryMd(agentName, ''), 'utf8');
|
||||||
|
// Create agents/<id>/ runtime directory (required by OpenClaw gateway)
|
||||||
|
const agentRuntimeDir = path.join(OPENCLAW_DIR, 'agents', agentId);
|
||||||
|
await fsp.mkdir(agentRuntimeDir, { recursive: true });
|
||||||
|
await fsp.mkdir(path.join(agentRuntimeDir, 'sessions'), { recursive: true });
|
||||||
res.writeHead(200);
|
res.writeHead(200);
|
||||||
res.end(JSON.stringify({
|
res.end(JSON.stringify({
|
||||||
ok: true, agentId, workspacePath: wsPath, configBackup: bakPath,
|
ok: true, agentId, workspacePath: wsPath, configBackup: bakPath,
|
||||||
notes: [
|
notes: [
|
||||||
'Agent created with its own bot token',
|
'Agent created with its own bot token',
|
||||||
'Workspace directory created with SOUL.md and MEMORY.md',
|
'Workspace directory created with SOUL.md and MEMORY.md',
|
||||||
|
'Runtime directory created at agents/' + agentId + '/',
|
||||||
'Configuration updated and backed up',
|
'Configuration updated and backed up',
|
||||||
'Changes take effect in ~300ms without restart'
|
'Restart gateway to load new bot: openclaw gateway restart'
|
||||||
]
|
]
|
||||||
}));
|
}));
|
||||||
return;
|
return;
|
||||||
@@ -487,13 +492,17 @@ async function handleApi(req, res, urlObj, body) {
|
|||||||
const name = displayName || agentId;
|
const name = displayName || agentId;
|
||||||
await fsp.writeFile(path.join(wsPath, 'SOUL.md'), generateSoulMd(name, purpose, personality), 'utf8');
|
await fsp.writeFile(path.join(wsPath, 'SOUL.md'), generateSoulMd(name, purpose, personality), 'utf8');
|
||||||
await fsp.writeFile(path.join(wsPath, 'MEMORY.md'), generateMemoryMd(name, initialMemory), 'utf8');
|
await fsp.writeFile(path.join(wsPath, 'MEMORY.md'), generateMemoryMd(name, initialMemory), 'utf8');
|
||||||
|
// Create agents/<id>/ runtime directory (required by OpenClaw gateway)
|
||||||
|
const agentRuntimeDir = path.join(OPENCLAW_DIR, 'agents', agentId);
|
||||||
|
await fsp.mkdir(agentRuntimeDir, { recursive: true });
|
||||||
|
await fsp.mkdir(path.join(agentRuntimeDir, 'sessions'), { recursive: true });
|
||||||
res.writeHead(200);
|
res.writeHead(200);
|
||||||
res.end(JSON.stringify({ ok: true, agentId, workspacePath: wsPath, configBackup: bakPath,
|
res.end(JSON.stringify({ ok: true, agentId, workspacePath: wsPath, configBackup: bakPath,
|
||||||
notes: [
|
notes: [
|
||||||
'Sub-agent created and shares parent bot',
|
'Sub-agent created and shares parent bot',
|
||||||
'Workspace directory created with SOUL.md and MEMORY.md',
|
'Workspace and runtime directories created',
|
||||||
'Configuration updated and backed up',
|
'Configuration updated and backed up',
|
||||||
'Changes take effect in ~300ms without restart'
|
'Restart gateway to apply: openclaw gateway restart'
|
||||||
],
|
],
|
||||||
}));
|
}));
|
||||||
return;
|
return;
|
||||||
@@ -2533,6 +2542,11 @@ function buildAddAgentForm() {
|
|||||||
'<div class="form-group"><label>' + t('wiz.model') + '</label>' +
|
'<div class="form-group"><label>' + t('wiz.model') + '</label>' +
|
||||||
'<select id="fa-model">' + modelOpts + '</select>' +
|
'<select id="fa-model">' + modelOpts + '</select>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
|
'<div class="form-group"><label>' + t('wiz.purpose') + '</label>' +
|
||||||
|
'<textarea id="fa-purpose" placeholder="' + t('wiz.purposePh') + '" rows="2"></textarea></div>' +
|
||||||
|
'<div class="form-group"><label>' + t('wiz.soul') + ' <span style="color:var(--muted);font-weight:400">' + t('wiz.soulHint') + '</span></label>' +
|
||||||
|
'<input id="fa-soul" placeholder="' + t('wiz.soulPh') + '">' +
|
||||||
|
'<span class="hint-text">' + t('wiz.soulTip') + '</span></div>' +
|
||||||
'<div style="display:flex;gap:8px;margin-top:14px">' +
|
'<div style="display:flex;gap:8px;margin-top:14px">' +
|
||||||
'<button class="btn-primary" onclick="submitAddAgent()">' + t('agents.addAgentSubmit') + '</button>' +
|
'<button class="btn-primary" onclick="submitAddAgent()">' + t('agents.addAgentSubmit') + '</button>' +
|
||||||
'<button class="btn-ghost" onclick="clearAddForm()">' + t('btn.cancel') + '</button>' +
|
'<button class="btn-ghost" onclick="clearAddForm()">' + t('btn.cancel') + '</button>' +
|
||||||
@@ -2590,13 +2604,15 @@ async function submitAddAgent() {
|
|||||||
const name = document.getElementById('fa-name').value.trim();
|
const name = document.getElementById('fa-name').value.trim();
|
||||||
const workspace = document.getElementById('fa-workspace').value.trim();
|
const workspace = document.getElementById('fa-workspace').value.trim();
|
||||||
const model = document.getElementById('fa-model').value;
|
const model = document.getElementById('fa-model').value;
|
||||||
|
const purpose = (document.getElementById('fa-purpose')?.value||'').trim();
|
||||||
|
const personality = (document.getElementById('fa-soul')?.value||'').trim();
|
||||||
if (!token) { toast(t('agents.errToken'), 'err'); return; }
|
if (!token) { toast(t('agents.errToken'), 'err'); return; }
|
||||||
if (!agentId) { toast('Agent ID is required', 'err'); return; }
|
if (!agentId) { toast('Agent ID is required', 'err'); return; }
|
||||||
if (!/^[a-zA-Z0-9_-]+$/.test(agentId)) { toast('Agent ID must contain only alphanumeric characters, underscores, or dashes', 'err'); return; }
|
if (!/^[a-zA-Z0-9_-]+$/.test(agentId)) { toast('Agent ID must contain only alphanumeric characters, underscores, or dashes', 'err'); return; }
|
||||||
if (!name) { toast(t('agents.errName'), 'err'); return; }
|
if (!name) { toast(t('agents.errName'), 'err'); return; }
|
||||||
if (!workspace) { toast('Workspace name is required', 'err'); return; }
|
if (!workspace) { toast('Workspace name is required', 'err'); return; }
|
||||||
try {
|
try {
|
||||||
const payload = { botToken: token, agentId, name, workspace, model: model === '__default__' ? '' : model };
|
const payload = { botToken: token, agentId, name, workspace, model: model === '__default__' ? '' : model, purpose, personality };
|
||||||
const r = await api('POST', '/api/agents/bot', payload);
|
const r = await api('POST', '/api/agents/bot', payload);
|
||||||
toast('Agent created successfully', 'ok');
|
toast('Agent created successfully', 'ok');
|
||||||
closePopover();
|
closePopover();
|
||||||
|
|||||||
Reference in New Issue
Block a user