141 lines
4.6 KiB
TypeScript
141 lines
4.6 KiB
TypeScript
import os from "node:os";
|
|
import path from "node:path";
|
|
|
|
import type { ClawdbotConfig } from "../config/config.js";
|
|
import { resolveStateDir } from "../config/paths.js";
|
|
import {
|
|
DEFAULT_AGENT_ID,
|
|
normalizeAgentId,
|
|
parseAgentSessionKey,
|
|
} from "../routing/session-key.js";
|
|
import { resolveUserPath } from "../utils.js";
|
|
import { DEFAULT_AGENT_WORKSPACE_DIR } from "./workspace.js";
|
|
|
|
export { resolveAgentIdFromSessionKey } from "../routing/session-key.js";
|
|
|
|
type AgentEntry = NonNullable<
|
|
NonNullable<ClawdbotConfig["agents"]>["list"]
|
|
>[number];
|
|
|
|
type ResolvedAgentConfig = {
|
|
name?: string;
|
|
workspace?: string;
|
|
agentDir?: string;
|
|
model?: string;
|
|
memorySearch?: AgentEntry["memorySearch"];
|
|
humanDelay?: AgentEntry["humanDelay"];
|
|
identity?: AgentEntry["identity"];
|
|
groupChat?: AgentEntry["groupChat"];
|
|
subagents?: AgentEntry["subagents"];
|
|
sandbox?: AgentEntry["sandbox"];
|
|
tools?: AgentEntry["tools"];
|
|
};
|
|
|
|
let defaultAgentWarned = false;
|
|
|
|
function listAgents(cfg: ClawdbotConfig): AgentEntry[] {
|
|
const list = cfg.agents?.list;
|
|
if (!Array.isArray(list)) return [];
|
|
return list.filter((entry): entry is AgentEntry =>
|
|
Boolean(entry && typeof entry === "object"),
|
|
);
|
|
}
|
|
|
|
export function resolveDefaultAgentId(cfg: ClawdbotConfig): string {
|
|
const agents = listAgents(cfg);
|
|
if (agents.length === 0) return DEFAULT_AGENT_ID;
|
|
const defaults = agents.filter((agent) => agent?.default);
|
|
if (defaults.length > 1 && !defaultAgentWarned) {
|
|
defaultAgentWarned = true;
|
|
console.warn(
|
|
"Multiple agents marked default=true; using the first entry as default.",
|
|
);
|
|
}
|
|
const chosen = (defaults[0] ?? agents[0])?.id?.trim();
|
|
return normalizeAgentId(chosen || DEFAULT_AGENT_ID);
|
|
}
|
|
|
|
export function resolveSessionAgentIds(params: {
|
|
sessionKey?: string;
|
|
config?: ClawdbotConfig;
|
|
}): { defaultAgentId: string; sessionAgentId: string } {
|
|
const defaultAgentId = resolveDefaultAgentId(params.config ?? {});
|
|
const sessionKey = params.sessionKey?.trim();
|
|
const parsed = sessionKey ? parseAgentSessionKey(sessionKey) : null;
|
|
const sessionAgentId = parsed?.agentId
|
|
? normalizeAgentId(parsed.agentId)
|
|
: defaultAgentId;
|
|
return { defaultAgentId, sessionAgentId };
|
|
}
|
|
|
|
export function resolveSessionAgentId(params: {
|
|
sessionKey?: string;
|
|
config?: ClawdbotConfig;
|
|
}): string {
|
|
return resolveSessionAgentIds(params).sessionAgentId;
|
|
}
|
|
|
|
function resolveAgentEntry(
|
|
cfg: ClawdbotConfig,
|
|
agentId: string,
|
|
): AgentEntry | undefined {
|
|
const id = normalizeAgentId(agentId);
|
|
return listAgents(cfg).find((entry) => normalizeAgentId(entry.id) === id);
|
|
}
|
|
|
|
export function resolveAgentConfig(
|
|
cfg: ClawdbotConfig,
|
|
agentId: string,
|
|
): ResolvedAgentConfig | undefined {
|
|
const id = normalizeAgentId(agentId);
|
|
const entry = resolveAgentEntry(cfg, id);
|
|
if (!entry) return undefined;
|
|
return {
|
|
name: typeof entry.name === "string" ? entry.name : undefined,
|
|
workspace:
|
|
typeof entry.workspace === "string" ? entry.workspace : undefined,
|
|
agentDir: typeof entry.agentDir === "string" ? entry.agentDir : undefined,
|
|
model: typeof entry.model === "string" ? entry.model : undefined,
|
|
memorySearch: entry.memorySearch,
|
|
humanDelay: entry.humanDelay,
|
|
identity: entry.identity,
|
|
groupChat: entry.groupChat,
|
|
subagents:
|
|
typeof entry.subagents === "object" && entry.subagents
|
|
? entry.subagents
|
|
: undefined,
|
|
sandbox: entry.sandbox,
|
|
tools: entry.tools,
|
|
};
|
|
}
|
|
|
|
export function resolveAgentWorkspaceDir(cfg: ClawdbotConfig, agentId: string) {
|
|
const id = normalizeAgentId(agentId);
|
|
const configured = resolveAgentConfig(cfg, id)?.workspace?.trim();
|
|
if (configured) return resolveUserPath(configured);
|
|
const defaultAgentId = resolveDefaultAgentId(cfg);
|
|
if (id === defaultAgentId) {
|
|
const fallback = cfg.agents?.defaults?.workspace?.trim();
|
|
if (fallback) return resolveUserPath(fallback);
|
|
return DEFAULT_AGENT_WORKSPACE_DIR;
|
|
}
|
|
return path.join(os.homedir(), `clawd-${id}`);
|
|
}
|
|
|
|
export function resolveAgentDir(cfg: ClawdbotConfig, agentId: string) {
|
|
const id = normalizeAgentId(agentId);
|
|
const configured = resolveAgentConfig(cfg, id)?.agentDir?.trim();
|
|
if (configured) return resolveUserPath(configured);
|
|
const root = resolveStateDir(process.env, os.homedir);
|
|
return path.join(root, "agents", id, "agent");
|
|
}
|
|
|
|
/**
|
|
* Resolve the agent directory for the default agent without requiring config.
|
|
* Used by onboarding when writing auth profiles before config is fully set up.
|
|
*/
|
|
export function resolveDefaultAgentDir(): string {
|
|
const root = resolveStateDir(process.env, os.homedir);
|
|
return path.join(root, "agents", DEFAULT_AGENT_ID, "agent");
|
|
}
|