Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion messages/ar.json
Original file line number Diff line number Diff line change
Expand Up @@ -1580,7 +1580,10 @@
"justNow": "الآن",
"minutesAgo": "منذ {count} د",
"hoursAgo": "منذ {count} س",
"daysAgo": "منذ {count} ي"
"daysAgo": "منذ {count} ي",
"runtimeType": "Runtime",
"runtimeTypeAuto": "Auto-detect",
"runtimeTypeCustom": "Custom"
},
"multiGateway": {
"title": "مدير البوابات",
Expand Down
5 changes: 4 additions & 1 deletion messages/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -1580,7 +1580,10 @@
"justNow": "Gerade eben",
"minutesAgo": "vor {count}m",
"hoursAgo": "vor {count}h",
"daysAgo": "vor {count}d"
"daysAgo": "vor {count}d",
"runtimeType": "Runtime",
"runtimeTypeAuto": "Auto-detect",
"runtimeTypeCustom": "Custom"
},
"multiGateway": {
"title": "Gateway-Manager",
Expand Down
5 changes: 4 additions & 1 deletion messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1729,7 +1729,10 @@
"justNow": "Just now",
"minutesAgo": "{count}m ago",
"hoursAgo": "{count}h ago",
"daysAgo": "{count}d ago"
"daysAgo": "{count}d ago",
"runtimeType": "Runtime",
"runtimeTypeAuto": "Auto-detect",
"runtimeTypeCustom": "Custom"
},
"multiGateway": {
"title": "Gateway Manager",
Expand Down
5 changes: 4 additions & 1 deletion messages/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -1580,7 +1580,10 @@
"justNow": "Ahora mismo",
"minutesAgo": "hace {count}m",
"hoursAgo": "hace {count}h",
"daysAgo": "hace {count}d"
"daysAgo": "hace {count}d",
"runtimeType": "Runtime",
"runtimeTypeAuto": "Auto-detect",
"runtimeTypeCustom": "Custom"
},
"multiGateway": {
"title": "Gestor de puertas de enlace",
Expand Down
5 changes: 4 additions & 1 deletion messages/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -1580,7 +1580,10 @@
"justNow": "À l'instant",
"minutesAgo": "il y a {count}m",
"hoursAgo": "il y a {count}h",
"daysAgo": "il y a {count}j"
"daysAgo": "il y a {count}j",
"runtimeType": "Runtime",
"runtimeTypeAuto": "Auto-detect",
"runtimeTypeCustom": "Custom"
},
"multiGateway": {
"title": "Gestionnaire de passerelles",
Expand Down
5 changes: 4 additions & 1 deletion messages/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -1580,7 +1580,10 @@
"justNow": "たった今",
"minutesAgo": "{count}分前",
"hoursAgo": "{count}時間前",
"daysAgo": "{count}日前"
"daysAgo": "{count}日前",
"runtimeType": "Runtime",
"runtimeTypeAuto": "Auto-detect",
"runtimeTypeCustom": "Custom"
},
"multiGateway": {
"title": "ゲートウェイマネージャー",
Expand Down
5 changes: 4 additions & 1 deletion messages/ko.json
Original file line number Diff line number Diff line change
Expand Up @@ -1729,7 +1729,10 @@
"justNow": "방금",
"minutesAgo": "{count}분 전",
"hoursAgo": "{count}시간 전",
"daysAgo": "{count}일 전"
"daysAgo": "{count}일 전",
"runtimeType": "Runtime",
"runtimeTypeAuto": "Auto-detect",
"runtimeTypeCustom": "Custom"
},
"multiGateway": {
"title": "게이트웨이 관리자",
Expand Down
5 changes: 4 additions & 1 deletion messages/pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -1580,7 +1580,10 @@
"justNow": "Agora mesmo",
"minutesAgo": "há {count}m",
"hoursAgo": "há {count}h",
"daysAgo": "há {count}d"
"daysAgo": "há {count}d",
"runtimeType": "Runtime",
"runtimeTypeAuto": "Auto-detect",
"runtimeTypeCustom": "Custom"
},
"multiGateway": {
"title": "Gerenciador de gateways",
Expand Down
5 changes: 4 additions & 1 deletion messages/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -1580,7 +1580,10 @@
"justNow": "Только что",
"minutesAgo": "{count}м назад",
"hoursAgo": "{count}ч назад",
"daysAgo": "{count}д назад"
"daysAgo": "{count}д назад",
"runtimeType": "Runtime",
"runtimeTypeAuto": "Auto-detect",
"runtimeTypeCustom": "Custom"
},
"multiGateway": {
"title": "Менеджер шлюзов",
Expand Down
5 changes: 4 additions & 1 deletion messages/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -1818,7 +1818,10 @@
"justNow": "刚刚",
"minutesAgo": "{count}分钟前",
"hoursAgo": "{count}小时前",
"daysAgo": "{count}天前"
"daysAgo": "{count}天前",
"runtimeType": "Runtime",
"runtimeTypeAuto": "Auto-detect",
"runtimeTypeCustom": "Custom"
},
"multiGateway": {
"title": "网关管理器",
Expand Down
41 changes: 34 additions & 7 deletions src/app/api/agents/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,8 @@ export async function POST(request: NextRequest) {
gateway_config,
write_to_gateway,
provision_openclaw_workspace,
openclaw_workspace_path
openclaw_workspace_path,
runtime_type,
} = body;

const openclawId = (openclaw_id || name || 'agent')
Expand Down Expand Up @@ -239,11 +240,11 @@ export async function POST(request: NextRequest) {

const stmt = db.prepare(`
INSERT INTO agents (
name, role, session_key, soul_content, status,
created_at, updated_at, config, workspace_id
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
name, role, session_key, soul_content, status,
created_at, updated_at, config, workspace_id, runtime_type
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`);

const dbResult = stmt.run(
name,
finalRole,
Expand All @@ -253,11 +254,37 @@ export async function POST(request: NextRequest) {
now,
now,
JSON.stringify(finalConfig),
workspaceId
workspaceId,
runtime_type || null
);

const agentId = dbResult.lastInsertRowid as number;


// Provision Hermes profile directory if runtime_type is hermes
if (runtime_type === 'hermes') {
try {
const { mkdirSync, writeFileSync, existsSync: fsExists } = require('node:fs')
const profileDir = path.join(appConfig.homeDir, '.hermes', 'profiles', name)
if (!fsExists(profileDir)) {
mkdirSync(profileDir, { recursive: true })
// Write config.yaml with model from agent config or default
const model = finalConfig.model || 'claude-sonnet-4-6'
const provider = finalConfig.provider || 'anthropic'
writeFileSync(
path.join(profileDir, 'config.yaml'),
`model: ${model}\nprovider: ${provider}\ntoolsets:\n- all\nmax_turns: 100\n`,
)
// Write SOUL.md if soul_content provided
if (soul_content) {
writeFileSync(path.join(profileDir, 'SOUL.md'), soul_content)
}
logger.info({ agentName: name, profileDir }, 'Provisioned Hermes profile directory')
}
} catch (err) {
logger.warn({ err, agentName: name }, 'Failed to provision Hermes profile (non-fatal)')
}
}

// Log activity
db_helpers.logActivity(
'agent_created',
Expand Down
32 changes: 30 additions & 2 deletions src/components/panels/agent-squad-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ interface Agent {
in_progress: number
completed: number
}
runtime_type?: string
}

const statusColors: Record<string, string> = {
Expand Down Expand Up @@ -217,7 +218,14 @@ export function AgentSquadPanel() {
{/* Agent Header */}
<div className="flex items-start justify-between mb-3">
<div>
<h3 className="font-semibold text-white text-lg">{agent.name}</h3>
<div className="flex items-center gap-2">
<h3 className="font-semibold text-white text-lg">{agent.name}</h3>
{agent.runtime_type && (
<span className="text-[10px] px-1.5 py-0.5 rounded bg-surface-1 text-muted-foreground border border-border/30">
{agent.runtime_type}
</span>
)}
</div>
<p className="text-gray-400 text-sm">{agent.role}</p>
</div>

Expand Down Expand Up @@ -528,6 +536,7 @@ function CreateAgentModal({
role: '',
session_key: '',
soul_content: '',
runtime_type: '' as string,
})

const handleSubmit = async (e: React.FormEvent) => {
Expand All @@ -537,7 +546,10 @@ function CreateAgentModal({
const response = await fetch('/api/agents', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(formData)
body: JSON.stringify({
...formData,
runtime_type: formData.runtime_type || undefined,
})
})

if (!response.ok) throw new Error(t('failedToCreate'))
Expand Down Expand Up @@ -579,6 +591,22 @@ function CreateAgentModal({
/>
</div>

<div>
<label className="block text-sm text-gray-400 mb-1">{t('runtimeType')}</label>
<select
value={formData.runtime_type}
onChange={(e) => setFormData(prev => ({ ...prev, runtime_type: e.target.value }))}
className="w-full bg-gray-700 text-white rounded px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
>
<option value="">{t('runtimeTypeAuto')}</option>
<option value="hermes">Hermes Agent</option>
<option value="openclaw">OpenClaw</option>
<option value="claude">Claude Code</option>
<option value="codex">Codex CLI</option>
<option value="custom">{t('runtimeTypeCustom')}</option>
</select>
</div>

<div>
<label className="block text-sm text-gray-400 mb-1">{t('sessionKeyOptional')}</label>
<input
Expand Down
6 changes: 6 additions & 0 deletions src/lib/migrations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1410,6 +1410,12 @@ const migrations: Migration[] = [
)
`)
}
},
{
id: '049_agent_runtime_type',
up(db: Database.Database) {
db.exec(`ALTER TABLE agents ADD COLUMN runtime_type TEXT DEFAULT NULL`)
}
}
]

Expand Down
1 change: 1 addition & 0 deletions src/lib/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export const createAgentSchema = z.object({
write_to_gateway: z.boolean().optional(),
provision_openclaw_workspace: z.boolean().optional(),
openclaw_workspace_path: z.string().min(1).max(500).optional(),
runtime_type: z.enum(['hermes', 'openclaw', 'claude', 'codex', 'custom']).optional(),
})

export const bulkUpdateTaskStatusSchema = z.object({
Expand Down
Loading