AkurAI Build
Menu

popagent

public

Latest change 4fc0bd53b97c085d906737f5b8b55d5771472d9c - feat: make company staff specialist agents by AkurAI Build

import { storage } from "./storage";
import {
  AGENT_TOOL_NAMES,
  BUILD_AGENT_IDS,
  BUILD_AGENT_TOOL_ALLOWLISTS,
  MAX_AGENT_INSTRUCTIONS_CHARACTERS,
  type AgentSettings,
  type AgentSettingsInput,
  type AgentToolName,
  type BuildAgentId,
} from "./api-types";
import { companyAgentProfiles } from "./company-roster";
import { retryableInit } from "./retryable-init";

const AGENT_SETTINGS_COLUMNS = `id, name, description, instructions,
  model,
  workspace_access AS "workspaceAccess", browser_access AS "browserAccess",
  delegation_enabled AS "delegationEnabled",
  tools, source_urls AS "sourceUrls",
  created_at::text AS "createdAt", updated_at::text AS "updatedAt"`;
const AGENT_TOOL_NAME_SET = new Set<string>(AGENT_TOOL_NAMES);
const BUILD_AGENT_ID_SET = new Set<string>(BUILD_AGENT_IDS);
const BUILD_AGENT_TOOL_SET = new Set<string>(
  Object.values(BUILD_AGENT_TOOL_ALLOWLISTS).flat(),
);

const initializeAgentRoleStorageOnce = retryableInit(async () => {
  await storage.init();
  const seed = await Bun.file(new URL("./agent-role-seed.sql", import.meta.url)).text();
  await storage.db.none(seed);
  await storage.db.tx(async (db) => {
    const migrationId = "2026-08-16-company-specialist-agents-v1";
    if (await db.oneOrNone("SELECT id FROM popagent_data_migrations WHERE id=$1", [migrationId])) return;
    for (const profile of companyAgentProfiles) {
      if (!profile.established) await db.none(`
        INSERT INTO popagent_agents
          (id, name, description, instructions, model, source_urls, workspace_access,
           browser_access, delegation_enabled, tools)
        VALUES ($1, $2, $3, $4, $5, $9::jsonb, $6, $7, TRUE, $8::jsonb)
        ON CONFLICT (id) DO NOTHING
      `, [
        profile.id, profile.name, profile.description, profile.instructions,
        "codex/gpt-5.6-luna-medium", profile.workspaceAccess, profile.browserAccess,
        JSON.stringify(profile.tools), JSON.stringify(profile.sourceUrls),
      ]);
      await db.none(`
        INSERT INTO popagent_agent_skills
          (id, agent_id, name, description, instructions, "references", source_urls, enabled, user_invocable)
        VALUES ($1, $2, $3, $4, $5, '{}'::jsonb, $6::jsonb, TRUE, FALSE)
        ON CONFLICT (id) DO NOTHING
      `, [
        `builtin-${profile.id}-specialty`, profile.id, profile.skillName,
        profile.skillDescription, profile.skillInstructions, JSON.stringify(profile.sourceUrls),
      ]);
    }
    await db.none("INSERT INTO popagent_data_migrations (id) VALUES ($1)", [migrationId]);
  });
});

export function initializeAgentRoleStorage(): Promise<void> {
  return initializeAgentRoleStorageOnce();
}

export class AgentSettingsStore {
  readonly storage = storage;

  init(): Promise<void> {
    return initializeAgentRoleStorage();
  }

  async list(): Promise<AgentSettings[]> {
    await this.init();
    return this.storage.db.any<AgentSettings>(`
      SELECT ${AGENT_SETTINGS_COLUMNS}
      FROM popagent_agents ORDER BY name
    `);
  }

  async get(id: string): Promise<AgentSettings | undefined> {
    await this.init();
    return (await this.storage.db.oneOrNone<AgentSettings>(`
      SELECT ${AGENT_SETTINGS_COLUMNS}
      FROM popagent_agents WHERE id = $1
    `, [id])) ?? undefined;
  }

  async update(id: string, input: AgentSettingsInput): Promise<AgentSettings | undefined> {
    if (input.instructions.length > MAX_AGENT_INSTRUCTIONS_CHARACTERS) {
      throw new RangeError(`Agent instructions exceed ${MAX_AGENT_INSTRUCTIONS_CHARACTERS} characters`);
    }
    if (!input.name.trim() || !input.description.trim() || !input.instructions.trim()) {
      throw new RangeError("Agent name, description, and instructions must not be empty");
    }
    if (
      input.tools.some((tool) => !AGENT_TOOL_NAME_SET.has(tool))
      || new Set(input.tools).size !== input.tools.length
    ) {
      throw new RangeError("Agent tools contain an unsupported or duplicate tool");
    }
    if (BUILD_AGENT_ID_SET.has(id)) {
      const allowed = BUILD_AGENT_TOOL_ALLOWLISTS[id as BuildAgentId] as readonly AgentToolName[];
      if (input.tools.some((tool) => !allowed.includes(tool))) {
        throw new RangeError("Build agent tools exceed its role allowlist");
      }
    } else if (input.tools.some((tool) => BUILD_AGENT_TOOL_SET.has(tool))) {
      throw new RangeError("Non-Build agents cannot use AkurAI Build tools");
    }
    return (await this.storage.db.oneOrNone<AgentSettings>(`
      UPDATE popagent_agents
      SET name = $2,
          description = $3,
          model = $5,
          instructions = $4,
          workspace_access = $6,
          browser_access = $7,
          delegation_enabled = $8,
          tools = $9::jsonb
      WHERE id = $1
      RETURNING ${AGENT_SETTINGS_COLUMNS}
    `, [
      id,
      input.name.trim(),
      input.description.trim(),
      input.instructions,
      input.model?.trim() || null,
      input.workspaceAccess,
      input.browserAccess,
      input.delegationEnabled,
      JSON.stringify(input.tools),
    ])) ?? undefined;
  }
}

export const agentSettings = new AgentSettingsStore();