naisys
Version:
NAISYS - Autonomous AI agent runner with built-in context management and cost tracking
138 lines • 5.74 kB
JavaScript
import { resolveTemplateString, sanitizeSpendLimit } from "@naisys/common";
import path from "path";
import table from "text-table";
import { agentConfigCmd } from "../command/commandDefs.js";
export function createAgentConfig(localUserId, { globalConfig }, userService) {
let fullAgentConfig = loadConfig();
function loadConfig() {
const user = userService.getUserById(localUserId);
if (!user) {
throw new Error(`User with ID ${localUserId} not found`);
}
return buildFullAgentConfig(user.config, user.isEphemeral === true);
}
function buildFullAgentConfig(config, isEphemeral) {
// Sanitize spend limits
const spendLimitDollars = sanitizeSpendLimit(config.spendLimitDollars);
const spendLimitHours = sanitizeSpendLimit(config.spendLimitHours);
// Ephemeral subagents delegate spend-limit checks to their parent, so they
// don't need their own spendLimitDollars or a global one set.
if (!isEphemeral &&
spendLimitDollars === undefined &&
globalConfig().spendLimitDollars === undefined) {
throw `Agent config: Error, 'spendLimitDollars' needs to be defined in the .env file or agent config`;
}
// Resolve model configs
const varMaps = {
agent: config,
env: globalConfig().variableMap,
};
const shellModel = resolveTemplateString(config.shellModel, varMaps);
const imageModel = config.imageModel
? resolveTemplateString(config.imageModel, varMaps)
: undefined;
function resolveConfigVars(templateString) {
return resolveTemplateString(templateString, varMaps);
}
return {
...config,
spendLimitDollars,
spendLimitHours,
shellModel,
imageModel,
resolveConfigVars,
mailEnabled: !!config.mailEnabled,
chatEnabled: !!config.chatEnabled,
webEnabled: !!config.webEnabled,
browserEnabled: !!config.browserEnabled,
completeSessionEnabled: !!config.completeSessionEnabled,
wakeOnMessage: !!config.wakeOnMessage,
initialCommands: config.initialCommands ?? [],
commandProtection: config.commandProtection ?? "none",
debugPauseSeconds: config.debugPauseSeconds,
multipleCommandsEnabled: !!config.multipleCommandsEnabled,
workspacesEnabled: !!config.workspacesEnabled,
supervisorApiHints: !!config.supervisorApiHints,
};
}
function updateConfigField(field, value) {
const user = userService.getUserById(localUserId);
if (!user) {
throw new Error(`User with ID ${localUserId} not found`);
}
// Convert value to appropriate type
let typedValue = value;
if (value === "true")
typedValue = true;
else if (value === "false")
typedValue = false;
else if (!isNaN(Number(value)) && value.trim() !== "")
typedValue = Number(value);
// set field
user.config[field] = typedValue;
// Update in-memory only (not persisted)
fullAgentConfig = buildFullAgentConfig(user.config, user.isEphemeral === true);
}
function handleCommand(cmdArgs) {
const args = cmdArgs.trim().split(/\s+/).filter(Boolean);
const config = fullAgentConfig;
if (args.length === 0) {
// Show all config values as a table
const rows = Object.entries(config)
.filter(([, value]) => typeof value !== "function")
.map(([key, value]) => {
const displayValue = typeof value === "object" ? JSON.stringify(value) : String(value);
return [key, displayValue];
});
return table([["Name", "Value"], ...rows], { hsep: " | " });
}
else if (args.length === 1) {
// Show specific config value
const name = args[0];
const value = config[name];
if (value === undefined) {
return `Config field '${name}' not found`;
}
if (typeof value === "function") {
return `Config field '${name}' is a function and cannot be displayed`;
}
return typeof value === "object"
? JSON.stringify(value, null, 2)
: String(value);
}
else {
// Update config value (session-only, not persisted)
const name = args[0];
const value = args.slice(1).join(" ");
try {
updateConfigField(name, value);
return `Config field '${name}' updated to '${value}' (session only, not persisted)`;
}
catch (error) {
return `Failed to update config: ${error instanceof Error ? error.message : String(error)}`;
}
}
}
const registrableCommand = {
command: agentConfigCmd,
handleCommand,
};
// Hub mode only — returns undefined in local mode where the shell just
// inherits the parent process's cwd.
function getHomeDir() {
const naisysFolder = process.env.NAISYS_FOLDER;
if (!naisysFolder)
return undefined;
return path.join(naisysFolder, "users", fullAgentConfig.username);
}
return {
...registrableCommand,
agentConfig: () => fullAgentConfig,
reloadAgentConfig: () => {
fullAgentConfig = loadConfig();
},
updateConfigField,
getHomeDir,
};
}
//# sourceMappingURL=agentConfig.js.map