Governed substrate for autonomous agents: scoped identity (passports), audited actions, MCP workspace. Infra IPs and secrets redacted for public release.
105 lines
3.6 KiB
JavaScript
105 lines
3.6 KiB
JavaScript
/**
|
|
* Shared agent resolution helpers for CRUD controllers.
|
|
* Resolves model and provider references from row IDs to full data.
|
|
*/
|
|
|
|
import { dbGet } from '../../../database/connection.js';
|
|
import { safeParseJSON } from './shared.js';
|
|
|
|
/**
|
|
* Resolve a model reference (row ID or string) to model details.
|
|
*/
|
|
export async function resolveModel(modelRef) {
|
|
if (typeof modelRef === 'number') {
|
|
const modelRow = await dbGet(`
|
|
SELECT tr.data FROM table_rows tr
|
|
JOIN universal_tables ut ON tr.table_id = ut.id
|
|
WHERE tr.id = ? AND (ut.name LIKE '%Models%' OR ut.name LIKE '%models%')
|
|
`, [modelRef]);
|
|
if (modelRow) {
|
|
const modelData = safeParseJSON(modelRow.data, {});
|
|
return {
|
|
id: modelRef,
|
|
name: modelData.name || modelData.model_id,
|
|
model_id: modelData.model_id || modelData.api_id || 'gpt-4o'
|
|
};
|
|
}
|
|
}
|
|
return { id: null, name: modelRef, model_id: modelRef || 'gpt-4o' };
|
|
}
|
|
|
|
/**
|
|
* Resolve a provider/operator reference (row ID or string) to provider details.
|
|
*/
|
|
export async function resolveProvider(providerRef) {
|
|
if (typeof providerRef === 'number') {
|
|
const providerRow = await dbGet(`
|
|
SELECT tr.data FROM table_rows tr
|
|
JOIN universal_tables ut ON tr.table_id = ut.id
|
|
WHERE tr.id = ? AND (ut.name LIKE '%Operators%' OR ut.name LIKE '%Providers%')
|
|
`, [providerRef]);
|
|
if (providerRow) {
|
|
const providerData = safeParseJSON(providerRow.data, {});
|
|
return {
|
|
id: providerRef,
|
|
name: providerData.name,
|
|
api_identifier: (providerData.provider || providerData.api_identifier || providerData.name || 'openai').toLowerCase()
|
|
};
|
|
}
|
|
}
|
|
return { id: null, name: providerRef, api_identifier: providerRef || 'openai' };
|
|
}
|
|
|
|
/**
|
|
* Parse agent row data into a standardized agent object.
|
|
*/
|
|
export function parseAgentRow(row, data, extra = {}) {
|
|
let tools = [];
|
|
if (data.tools) {
|
|
try {
|
|
tools = typeof data.tools === 'string' ? safeParseJSON(data.tools, {}) : data.tools;
|
|
} catch (e) {
|
|
tools = [];
|
|
}
|
|
}
|
|
|
|
let tags = [];
|
|
if (data.tags) {
|
|
try {
|
|
tags = typeof data.tags === 'string' ? safeParseJSON(data.tags, []) : (Array.isArray(data.tags) ? data.tags : []);
|
|
} catch (e) {
|
|
tags = [];
|
|
}
|
|
}
|
|
|
|
const isActive = data.is_active === true || data.is_active === 1 ||
|
|
data.is_active === 'true' || data.is_active === '1' || data.status === 'active';
|
|
|
|
return {
|
|
id: row.id,
|
|
name: data.name || data.agent_name || 'Unnamed Agent',
|
|
description: data.description || '',
|
|
system_prompt: data.system_prompt || '',
|
|
icon: data.icon || data.avatar || '🤖',
|
|
color: data.color || '#3B82F6',
|
|
is_active: isActive,
|
|
api_key_id: data.api_key_id || null,
|
|
tools,
|
|
tags,
|
|
operator_id: data.operator_id,
|
|
status: data.status || 'active',
|
|
response_mode: data.response_mode || 'mention_only',
|
|
// ADR-0057 — surface invocation_mode and main_instructions to clients so
|
|
// the edit modal can show current state. Both default to null and are
|
|
// tolerant of missing keys (legacy rows pre-ADR-0057).
|
|
invocation_mode: data.invocation_mode || null,
|
|
main_instructions: data.main_instructions ?? data.main_instruction ?? null,
|
|
tables_config: data.tables_config || null,
|
|
context_settings: data.context_settings || null,
|
|
// ADR-0079: surface agent_slug + visibility so frontend agentVisibility filter
|
|
// and the promo-unlock merge below in agentCrudController can both run.
|
|
agent_slug: data.agent_slug || data.slug || null,
|
|
visibility: data.visibility || 'default',
|
|
...extra
|
|
};
|
|
}
|