feat: add --no-skills flag to disable bundled skills (#948)
Co-authored-by: Letta <noreply@letta.com>
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
interface AgentContext {
|
||||
agentId: string | null;
|
||||
skillsDirectory: string | null;
|
||||
noSkills: boolean;
|
||||
conversationId: string | null;
|
||||
}
|
||||
|
||||
@@ -23,6 +24,7 @@ function getContext(): AgentContext {
|
||||
global[CONTEXT_KEY] = {
|
||||
agentId: null,
|
||||
skillsDirectory: null,
|
||||
noSkills: false,
|
||||
conversationId: null,
|
||||
};
|
||||
}
|
||||
@@ -35,13 +37,16 @@ const context = getContext();
|
||||
* Set the current agent context
|
||||
* @param agentId - The agent ID
|
||||
* @param skillsDirectory - Optional skills directory path
|
||||
* @param noSkills - Whether to skip bundled skills
|
||||
*/
|
||||
export function setAgentContext(
|
||||
agentId: string,
|
||||
skillsDirectory?: string,
|
||||
noSkills?: boolean,
|
||||
): void {
|
||||
context.agentId = agentId;
|
||||
context.skillsDirectory = skillsDirectory || null;
|
||||
context.noSkills = noSkills ?? false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -70,6 +75,13 @@ export function getSkillsDirectory(): string | null {
|
||||
return context.skillsDirectory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether bundled skills should be skipped
|
||||
*/
|
||||
export function getNoSkills(): boolean {
|
||||
return context.noSkills;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current conversation ID
|
||||
* @param conversationId - The conversation ID, or null to clear
|
||||
|
||||
@@ -167,14 +167,17 @@ async function discoverSkillsFromDir(
|
||||
export async function discoverSkills(
|
||||
projectSkillsPath: string = join(process.cwd(), SKILLS_DIR),
|
||||
agentId?: string,
|
||||
options?: { skipBundled?: boolean },
|
||||
): Promise<SkillDiscoveryResult> {
|
||||
const allErrors: SkillDiscoveryError[] = [];
|
||||
const skillsById = new Map<string, Skill>();
|
||||
|
||||
// 1. Start with bundled skills (lowest priority)
|
||||
const bundledSkills = await getBundledSkills();
|
||||
for (const skill of bundledSkills) {
|
||||
skillsById.set(skill.id, skill);
|
||||
if (!options?.skipBundled) {
|
||||
const bundledSkills = await getBundledSkills();
|
||||
for (const skill of bundledSkills) {
|
||||
skillsById.set(skill.id, skill);
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Add global skills (override bundled)
|
||||
|
||||
@@ -8074,10 +8074,14 @@ ${SYSTEM_REMINDER_CLOSE}
|
||||
try {
|
||||
const { discoverSkills: discover, SKILLS_DIR: defaultDir } =
|
||||
await import("../agent/skills");
|
||||
const { getSkillsDirectory } = await import("../agent/context");
|
||||
const { getSkillsDirectory, getNoSkills } = await import(
|
||||
"../agent/context"
|
||||
);
|
||||
const skillsDir =
|
||||
getSkillsDirectory() || join(process.cwd(), defaultDir);
|
||||
const { skills } = await discover(skillsDir, agentId);
|
||||
const { skills } = await discover(skillsDir, agentId, {
|
||||
skipBundled: getNoSkills(),
|
||||
});
|
||||
discoveredSkillsRef.current = skills;
|
||||
} catch {
|
||||
discoveredSkillsRef.current = [];
|
||||
|
||||
@@ -79,6 +79,7 @@ export async function handleHeadlessCommand(
|
||||
argv: string[],
|
||||
model?: string,
|
||||
skillsDirectory?: string,
|
||||
noSkills?: boolean,
|
||||
) {
|
||||
const settings = settingsManager.getSettings();
|
||||
|
||||
@@ -125,6 +126,7 @@ export async function handleHeadlessCommand(
|
||||
|
||||
memfs: { type: "boolean" },
|
||||
"no-memfs": { type: "boolean" },
|
||||
"no-skills": { type: "boolean" },
|
||||
"max-turns": { type: "string" }, // Maximum number of agentic turns
|
||||
},
|
||||
strict: false,
|
||||
@@ -807,7 +809,7 @@ export async function handleHeadlessCommand(
|
||||
}
|
||||
|
||||
// Set agent context for tools that need it (e.g., Skill tool, Task tool)
|
||||
setAgentContext(agent.id, skillsDirectory);
|
||||
setAgentContext(agent.id, skillsDirectory, noSkills);
|
||||
|
||||
// Validate output format
|
||||
const outputFormat =
|
||||
@@ -1071,7 +1073,9 @@ ${SYSTEM_REMINDER_CLOSE}
|
||||
const { join } = await import("node:path");
|
||||
try {
|
||||
const skillsDir = getSkillsDirectory() || join(process.cwd(), defaultDir);
|
||||
const { skills } = await discoverSkills(skillsDir, agent.id);
|
||||
const { skills } = await discoverSkills(skillsDir, agent.id, {
|
||||
skipBundled: noSkills,
|
||||
});
|
||||
const skillsReminder = formatSkillsAsSystemReminder(skills);
|
||||
if (skillsReminder) {
|
||||
pushPart(skillsReminder);
|
||||
|
||||
11
src/index.ts
11
src/index.ts
@@ -442,6 +442,7 @@ async function main(): Promise<void> {
|
||||
|
||||
memfs: { type: "boolean" },
|
||||
"no-memfs": { type: "boolean" },
|
||||
"no-skills": { type: "boolean" },
|
||||
"max-turns": { type: "string" },
|
||||
},
|
||||
strict: true,
|
||||
@@ -553,6 +554,7 @@ async function main(): Promise<void> {
|
||||
const skillsDirectory = (values.skills as string | undefined) ?? undefined;
|
||||
const memfsFlag = values.memfs as boolean | undefined;
|
||||
const noMemfsFlag = values["no-memfs"] as boolean | undefined;
|
||||
const noSkillsFlag = values["no-skills"] as boolean | undefined;
|
||||
const fromAfFile =
|
||||
(values.import as string | undefined) ??
|
||||
(values["from-af"] as string | undefined);
|
||||
@@ -946,7 +948,12 @@ async function main(): Promise<void> {
|
||||
markMilestone("TOOLS_LOADED");
|
||||
|
||||
const { handleHeadlessCommand } = await import("./headless");
|
||||
await handleHeadlessCommand(process.argv, specifiedModel, skillsDirectory);
|
||||
await handleHeadlessCommand(
|
||||
process.argv,
|
||||
specifiedModel,
|
||||
skillsDirectory,
|
||||
noSkillsFlag,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1679,7 +1686,7 @@ async function main(): Promise<void> {
|
||||
}
|
||||
|
||||
// Set agent context for tools that need it (e.g., Skill tool)
|
||||
setAgentContext(agent.id, skillsDirectory);
|
||||
setAgentContext(agent.id, skillsDirectory, noSkillsFlag);
|
||||
|
||||
// Apply memfs flag if explicitly specified (memfs is opt-in via /memfs enable or --memfs)
|
||||
const isSubagent = process.env.LETTA_CODE_AGENT_ROLE === "subagent";
|
||||
|
||||
Reference in New Issue
Block a user