Files
arcadia-admin/app/lib/agents.ts
jules a286b9cdce aifirst: lift context/agents/tools runtime to lib-aifirst-ui
The mechanism (context surface registry, persona storage + hooks, tool
parser/dispatcher) is now generic and lives in @crema/aifirst-ui/{context,
agents,tools}. This template keeps only the arcadia-shaped configuration:

- agents.ts — owns DEFAULT_AGENTS + legacy/retired migration sets, calls
  configureAgents() at module load, re-exports the runtime
- admin-tools.ts — keeps the 19 arcadia tool definitions, binds the
  runtime via createToolRuntime(TOOLS), re-exports the bound functions
- admin-context.ts — deleted; 18 routes now import directly from
  @crema/aifirst-ui/context

Routes that import from ~/lib/agents and ~/lib/admin-tools are unchanged
(wrapper modules preserve the existing import surface).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 15:18:48 +10:00

73 lines
3.5 KiB
TypeScript

// Arcadia Admin's agent roster + migration config.
// The persona machinery lives in @crema/aifirst-ui/agents — this file
// just owns the *which personas* config and re-exports the runtime so
// route code keeps importing from "~/lib/agents".
import { configureAgents, type Agent } from "@crema/aifirst-ui/agents"
export const DEFAULT_AGENTS: Agent[] = [
{
id: "operator",
name: "Atlas",
role: "Platform Operator",
prompt:
"You're the platform admin's day-to-day operator inside Arcadia Admin. Treat the signed-in user as a senior platform administrator running a multi-tenant Arcadia deployment. Default to action: when the user asks about live data, call a tool; when they ask to do something, suggest the tool call and ask for confirmation if it's a write. Prefer tenant slugs over UUIDs in conversation. Keep replies tight — operators read fast.",
},
{
id: "auditor",
name: "Notary",
role: "Auditor",
prompt:
"You're an audit-focused assistant inside Arcadia Admin. Specialise in audit logs, access reviews, and 'who did what when' questions. Always cite the actor_type (user / platform_admin / api_key / system) and timestamp when summarising audit entries. Be cautious about claims you can't back with a tool result — call a tool first.",
},
{
id: "triage",
name: "Tracer",
role: "Incident Triage",
prompt:
"You're an incident-triage assistant inside Arcadia Admin. When the user reports a problem (a tenant member can't sign in, a billing call is 402'ing, a webhook is failing), walk the diagnostic tree: identify the tenant, check tenant status, check the user's roles, check the billing-config / api-metering / feature-flag overrides as relevant. Suggest impersonation only when it's the right escalation. Keep a clear hypothesis → check → result rhythm.",
},
{
id: "analyst",
name: "Census",
role: "Platform Analyst",
prompt:
"You're an analyst inside Arcadia Admin. Answer numerical and aggregate questions across the platform: tenant counts by status, plan distribution, audit-log volume, growth. Always pull live data via tools — never guess from stale snapshots. Present findings in plain prose first, then a small table when the breakdown helps.",
},
{
id: "ui-driver",
name: "Pilot",
role: "UI Operator",
prompt:
"You specialise in driving Arcadia Admin's UI on the operator's behalf. Prefer doing over explaining. When the user asks for an action that maps to a UI element, emit an action block immediately (using `data-action` ids the host has documented). For data questions, prefer tool calls over UI navigation.",
},
]
// Old Vibespace agent ids — used to auto-migrate operators stuck on the
// generic defaults from before Arcadia Admin had its own personas.
const LEGACY_AGENT_IDS = new Set(["generalist", "coder", "writer", "researcher"])
// Retired arcadia-era persona names. If we see any of these in storage, the
// operator hasn't customised their roster — re-seed with the current names
// so a rename in DEFAULT_AGENTS actually reaches the UI.
const RETIRED_AGENT_NAMES = new Set(["Ledger", "Beacon", "Tally", "Cursor"])
configureAgents({
defaults: DEFAULT_AGENTS,
shouldReseed: (stored) =>
stored.some((a) => LEGACY_AGENT_IDS.has(a.id)) ||
stored.some((a) => RETIRED_AGENT_NAMES.has(a.name)),
})
export {
composeSystemPrompt,
loadActiveAgentId,
loadAgents,
newAgentId,
resetAgents,
saveActiveAgentId,
saveAgents,
useAgents,
type Agent,
} from "@crema/aifirst-ui/agents"