feat: add client side skills (#1320)
Co-authored-by: Letta Code <noreply@letta.com>
This commit is contained in:
@@ -7,7 +7,6 @@ export type SharedReminderMode =
|
||||
export type SharedReminderId =
|
||||
| "session-context"
|
||||
| "agent-info"
|
||||
| "skills"
|
||||
| "permission-mode"
|
||||
| "plan-mode"
|
||||
| "reflection-step-count"
|
||||
@@ -40,11 +39,6 @@ export const SHARED_REMINDER_CATALOG: ReadonlyArray<SharedReminderDefinition> =
|
||||
"subagent",
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "skills",
|
||||
description: "Available skills system reminder (with reinjection)",
|
||||
modes: ["interactive", "headless-one-shot", "headless-bidirectional"],
|
||||
},
|
||||
{
|
||||
id: "permission-mode",
|
||||
description: "Permission mode reminder",
|
||||
|
||||
@@ -1,12 +1,5 @@
|
||||
import { join } from "node:path";
|
||||
import type { MessageCreate } from "@letta-ai/letta-client/resources/agents/agents";
|
||||
import { getSkillsDirectory } from "../agent/context";
|
||||
import {
|
||||
discoverSkills,
|
||||
formatSkillsAsSystemReminder,
|
||||
SKILLS_DIR,
|
||||
type SkillSource,
|
||||
} from "../agent/skills";
|
||||
import type { SkillSource } from "../agent/skills";
|
||||
import { buildAgentInfo } from "../cli/helpers/agentInfo";
|
||||
import {
|
||||
buildCompactionMemoryReminder,
|
||||
@@ -101,52 +94,6 @@ async function buildSessionContextReminder(
|
||||
return reminder || null;
|
||||
}
|
||||
|
||||
async function buildSkillsReminder(
|
||||
context: SharedReminderContext,
|
||||
): Promise<string | null> {
|
||||
const previousSkillsReminder = context.state.cachedSkillsReminder;
|
||||
// Keep a stable empty baseline so a later successful discovery can diff
|
||||
// against "" and trigger reinjection, even after an earlier discovery failure.
|
||||
let latestSkillsReminder = previousSkillsReminder ?? "";
|
||||
|
||||
try {
|
||||
const skillsDir = getSkillsDirectory() || join(process.cwd(), SKILLS_DIR);
|
||||
const { skills } = await discoverSkills(skillsDir, context.agent.id, {
|
||||
sources: context.skillSources,
|
||||
});
|
||||
latestSkillsReminder = formatSkillsAsSystemReminder(skills);
|
||||
context.state.skillPathById = Object.fromEntries(
|
||||
skills
|
||||
.filter(
|
||||
(skill) => typeof skill.path === "string" && skill.path.length > 0,
|
||||
)
|
||||
.map((skill) => [skill.id, skill.path as string]),
|
||||
);
|
||||
} catch {
|
||||
// Keep previous snapshot when discovery fails.
|
||||
}
|
||||
|
||||
if (
|
||||
previousSkillsReminder !== null &&
|
||||
previousSkillsReminder !== latestSkillsReminder
|
||||
) {
|
||||
context.state.pendingSkillsReinject = true;
|
||||
}
|
||||
|
||||
context.state.cachedSkillsReminder = latestSkillsReminder;
|
||||
|
||||
const shouldInject =
|
||||
!context.state.hasInjectedSkillsReminder ||
|
||||
context.state.pendingSkillsReinject;
|
||||
if (!shouldInject) {
|
||||
return null;
|
||||
}
|
||||
|
||||
context.state.hasInjectedSkillsReminder = true;
|
||||
context.state.pendingSkillsReinject = false;
|
||||
return latestSkillsReminder || null;
|
||||
}
|
||||
|
||||
async function buildPlanModeReminder(
|
||||
context: SharedReminderContext,
|
||||
): Promise<string | null> {
|
||||
@@ -398,7 +345,6 @@ export const sharedReminderProviders: Record<
|
||||
> = {
|
||||
"agent-info": buildAgentInfoReminder,
|
||||
"session-context": buildSessionContextReminder,
|
||||
skills: buildSkillsReminder,
|
||||
"permission-mode": buildPermissionModeReminder,
|
||||
"plan-mode": buildPlanModeReminder,
|
||||
"reflection-step-count": buildReflectionStepReminder,
|
||||
|
||||
@@ -22,12 +22,8 @@ export interface ToolsetChangeReminder {
|
||||
export interface SharedReminderState {
|
||||
hasSentAgentInfo: boolean;
|
||||
hasSentSessionContext: boolean;
|
||||
hasInjectedSkillsReminder: boolean;
|
||||
cachedSkillsReminder: string | null;
|
||||
skillPathById: Record<string, string>;
|
||||
lastNotifiedPermissionMode: PermissionMode | null;
|
||||
turnCount: number;
|
||||
pendingSkillsReinject: boolean;
|
||||
pendingReflectionTrigger: boolean;
|
||||
pendingAutoInitReminder: boolean;
|
||||
pendingCommandIoReminders: CommandIoReminder[];
|
||||
@@ -40,12 +36,8 @@ export function createSharedReminderState(): SharedReminderState {
|
||||
return {
|
||||
hasSentAgentInfo: false,
|
||||
hasSentSessionContext: false,
|
||||
hasInjectedSkillsReminder: false,
|
||||
cachedSkillsReminder: null,
|
||||
skillPathById: {},
|
||||
lastNotifiedPermissionMode: null,
|
||||
turnCount: 0,
|
||||
pendingSkillsReinject: false,
|
||||
pendingReflectionTrigger: false,
|
||||
pendingAutoInitReminder: false,
|
||||
pendingCommandIoReminders: [],
|
||||
@@ -63,10 +55,6 @@ export function syncReminderStateFromContextTracker(
|
||||
state: SharedReminderState,
|
||||
contextTracker: ContextTracker,
|
||||
): void {
|
||||
if (contextTracker.pendingSkillsReinject) {
|
||||
state.pendingSkillsReinject = true;
|
||||
contextTracker.pendingSkillsReinject = false;
|
||||
}
|
||||
if (contextTracker.pendingReflectionTrigger) {
|
||||
state.pendingReflectionTrigger = true;
|
||||
contextTracker.pendingReflectionTrigger = false;
|
||||
|
||||
Reference in New Issue
Block a user