q / core /agents.js
Humuhumu33's picture
Upload folder using huggingface_hub
3365e13 verified
Raw
History Blame Contribute Delete
3.74 kB
// core/agents.js — AGENTS as κ-objects (LibreChat agent semantics, substrate-native). An agent
// bundles identity + instructions + model + parameters + armed tools + conversation starters;
// selecting one shapes every turn (instructions ride the system block, its tool selection arms
// the MCP loop). Field names follow the LibreChat agent schema so exports interoperate; each
// version re-seals to a new κ (history is free, Law L3).
import { normPreset } from "./schema.js";
const LC = { lc: "https://librechat.ai/ns#" };
export function normAgent(a = {}) {
return {
id: typeof a.id === "string" ? a.id : null,
name: a.name || "New Agent",
description: a.description || "",
instructions: a.instructions || "",
avatar: a.avatar || null, // { filepath, source } | emoji string | null
provider: a.provider || "holo-q", // the local substrate engine
model: a.model || null, // a MODELS[] name
model_parameters: {
temperature: +(a.model_parameters?.temperature ?? 0) || 0,
max_output_tokens: +(a.model_parameters?.max_output_tokens ?? 900) || 900,
},
tools: Array.isArray(a.tools) ? a.tools : [], // armed tool names (the MCP loop selection)
mcpServerNames: Array.isArray(a.mcpServerNames) ? a.mcpServerNames : [],
conversation_starters: Array.isArray(a.conversation_starters) ? a.conversation_starters.filter(Boolean).slice(0, 4) : [],
artifacts: a.artifacts || "default", // 'default' | 'custom' (custom: instructions own the format)
recursion_limit: +(a.recursion_limit ?? 4) || 4, // max tool rounds
category: a.category || "general",
version: +(a.version ?? 1) || 1,
};
}
export function makeAgents(chatStore) {
const { store, getIndex, newId } = chatStore;
const putIndex = async (idx) => { const b = new TextEncoder().encode(JSON.stringify(idx)); return store.backend.putRaw ? store.backend.putRaw("index:org.hologram.HoloQ", b) : store.backend.put("index:org.hologram.HoloQ", b); };
async function save(a) {
const norm = normAgent(a);
if (!norm.id) norm.id = newId("agent");
const prevPtr = ((await getIndex()).agents || []).find((x) => x.id === norm.id);
if (prevPtr) norm.version = (prevPtr.version || 1) + 1;
const obj = await store.makeObject({
type: ["schema:SoftwareAgent", "prov:Entity"], context: [LC],
"schema:identifier": norm.id, "schema:name": norm.name, "schema:description": norm.description,
"lc:agent": norm,
...(prevPtr ? { links: [{ ...store.contentLink("prov:wasRevisionOf", prevPtr.kappa, "schema:SoftwareAgent"), "schema:name": "previousVersion" }] } : {}),
});
const idx = await getIndex();
idx.agents = idx.agents || [];
const ptr = { id: norm.id, kappa: obj.id, name: norm.name, avatar: norm.avatar, category: norm.category, version: norm.version };
const i = idx.agents.findIndex((x) => x.id === norm.id);
if (i >= 0) idx.agents[i] = ptr; else idx.agents.push(ptr);
await putIndex(idx);
return { ...norm, kappa: obj.id };
}
async function list() { return (await getIndex()).agents || []; }
async function get(id) {
const ptr = (await list()).find((x) => x.id === id); if (!ptr) return null;
const obj = await store.getObj(ptr.kappa); if (!obj) return null;
if (!(await store.verify(obj))) return null; // Law L5: a tampered agent is refused
return { ...normAgent(obj["lc:agent"]), kappa: ptr.kappa };
}
async function remove(id) {
const idx = await getIndex();
idx.agents = (idx.agents || []).filter((x) => x.id !== id);
await putIndex(idx);
}
return { save, list, get, remove, normAgent };
}