refactor(profile): simplify profile structure by removing identity and bootstrap
- Remove identity.md and bootstrap.md from profile files - Merge identity content into soul.md (now contains identity, personality, and behavior) - Update templates, storage, and types to reflect new structure - Update tests to match new profile structure Profile now has 4 files: soul.md, user.md, workspace.md, memory.md Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
9f48dca6af
commit
e7f84755b3
6 changed files with 38 additions and 98 deletions
|
|
@ -65,11 +65,10 @@ function cmdNew(profileId: string | undefined) {
|
|||
console.log(`Location: ${dir}`);
|
||||
console.log("");
|
||||
console.log("Files created:");
|
||||
console.log(" - soul.md (personality and constraints)");
|
||||
console.log(" - identity.md (name and role)");
|
||||
console.log(" - tools.md (tool usage instructions)");
|
||||
console.log(" - soul.md (identity, personality and behavior)");
|
||||
console.log(" - user.md (information about the user)");
|
||||
console.log(" - workspace.md (workspace rules and conventions)");
|
||||
console.log(" - memory.md (persistent knowledge)");
|
||||
console.log(" - bootstrap.md (initial context)");
|
||||
console.log("");
|
||||
console.log("Edit these files to customize your agent, then run:");
|
||||
console.log(` pnpm agent:cli --profile ${profileId} "Hello"`);
|
||||
|
|
@ -120,21 +119,21 @@ function cmdShow(profileId: string | undefined) {
|
|||
console.log(`Location: ${getProfileDir(profileId)}`);
|
||||
console.log("");
|
||||
|
||||
if (profile.identity) {
|
||||
console.log("=== identity.md ===");
|
||||
console.log(profile.identity.trim());
|
||||
console.log("");
|
||||
}
|
||||
|
||||
if (profile.soul) {
|
||||
console.log("=== soul.md ===");
|
||||
console.log(profile.soul.trim());
|
||||
console.log("");
|
||||
}
|
||||
|
||||
if (profile.tools) {
|
||||
console.log("=== tools.md ===");
|
||||
console.log(profile.tools.trim());
|
||||
if (profile.user) {
|
||||
console.log("=== user.md ===");
|
||||
console.log(profile.user.trim());
|
||||
console.log("");
|
||||
}
|
||||
|
||||
if (profile.workspace) {
|
||||
console.log("=== workspace.md ===");
|
||||
console.log(profile.workspace.trim());
|
||||
console.log("");
|
||||
}
|
||||
|
||||
|
|
@ -143,12 +142,6 @@ function cmdShow(profileId: string | undefined) {
|
|||
console.log(profile.memory.trim());
|
||||
console.log("");
|
||||
}
|
||||
|
||||
if (profile.bootstrap) {
|
||||
console.log("=== bootstrap.md ===");
|
||||
console.log(profile.bootstrap.trim());
|
||||
console.log("");
|
||||
}
|
||||
}
|
||||
|
||||
async function cmdEdit(profileId: string | undefined) {
|
||||
|
|
|
|||
|
|
@ -43,11 +43,9 @@ export function createAgentProfile(
|
|||
// 如果使用模板,填充默认内容
|
||||
if (useTemplates) {
|
||||
profile.soul = DEFAULT_TEMPLATES.soul;
|
||||
profile.identity = DEFAULT_TEMPLATES.identity;
|
||||
profile.user = DEFAULT_TEMPLATES.user;
|
||||
profile.workspace = DEFAULT_TEMPLATES.workspace;
|
||||
profile.memory = DEFAULT_TEMPLATES.memory;
|
||||
profile.bootstrap = DEFAULT_TEMPLATES.bootstrap;
|
||||
|
||||
// 保存到文件
|
||||
saveProfile(profile, { baseDir });
|
||||
|
|
@ -137,10 +135,6 @@ export class ProfileManager {
|
|||
|
||||
const parts: string[] = [];
|
||||
|
||||
if (profile.identity) {
|
||||
parts.push(profile.identity);
|
||||
}
|
||||
|
||||
if (profile.soul) {
|
||||
parts.push(profile.soul);
|
||||
}
|
||||
|
|
@ -157,10 +151,6 @@ export class ProfileManager {
|
|||
parts.push(profile.memory);
|
||||
}
|
||||
|
||||
if (profile.bootstrap) {
|
||||
parts.push(profile.bootstrap);
|
||||
}
|
||||
|
||||
// 注入 profile 目录路径,让 Agent 知道文件在哪里
|
||||
const profileDir = this.getProfileDir();
|
||||
parts.push(`## Profile Directory\n\nYour profile files are located at: \`${profileDir}\`\n\nUse \`edit\` or \`write\` tools to update these files when needed.`);
|
||||
|
|
|
|||
|
|
@ -150,22 +150,18 @@ describe("storage", () => {
|
|||
const dir = join(testBaseDir, profileId);
|
||||
mkdirSync(dir, { recursive: true });
|
||||
|
||||
writeFileSync(join(dir, "SOUL.md"), "Soul content");
|
||||
writeFileSync(join(dir, "IDENTITY.md"), "Identity content");
|
||||
writeFileSync(join(dir, "USER.md"), "User content");
|
||||
writeFileSync(join(dir, "WORKSPACE.md"), "Workspace content");
|
||||
writeFileSync(join(dir, "MEMORY.md"), "Memory content");
|
||||
writeFileSync(join(dir, "BOOTSTRAP.md"), "Bootstrap content");
|
||||
writeFileSync(join(dir, "soul.md"), "Soul content");
|
||||
writeFileSync(join(dir, "user.md"), "User content");
|
||||
writeFileSync(join(dir, "workspace.md"), "Workspace content");
|
||||
writeFileSync(join(dir, "memory.md"), "Memory content");
|
||||
|
||||
const profile = loadProfile(profileId, { baseDir: testBaseDir });
|
||||
|
||||
expect(profile.id).toBe(profileId);
|
||||
expect(profile.soul).toBe("Soul content");
|
||||
expect(profile.identity).toBe("Identity content");
|
||||
expect(profile.user).toBe("User content");
|
||||
expect(profile.workspace).toBe("Workspace content");
|
||||
expect(profile.memory).toBe("Memory content");
|
||||
expect(profile.bootstrap).toBe("Bootstrap content");
|
||||
});
|
||||
|
||||
it("should return undefined for missing files", () => {
|
||||
|
|
@ -173,17 +169,15 @@ describe("storage", () => {
|
|||
const dir = join(testBaseDir, profileId);
|
||||
mkdirSync(dir, { recursive: true });
|
||||
|
||||
writeFileSync(join(dir, "SOUL.md"), "Soul only");
|
||||
writeFileSync(join(dir, "soul.md"), "Soul only");
|
||||
|
||||
const profile = loadProfile(profileId, { baseDir: testBaseDir });
|
||||
|
||||
expect(profile.id).toBe(profileId);
|
||||
expect(profile.soul).toBe("Soul only");
|
||||
expect(profile.identity).toBeUndefined();
|
||||
expect(profile.user).toBeUndefined();
|
||||
expect(profile.workspace).toBeUndefined();
|
||||
expect(profile.memory).toBeUndefined();
|
||||
expect(profile.bootstrap).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should handle non-existent profile", () => {
|
||||
|
|
@ -191,7 +185,6 @@ describe("storage", () => {
|
|||
|
||||
expect(profile.id).toBe("non-existent");
|
||||
expect(profile.soul).toBeUndefined();
|
||||
expect(profile.identity).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -200,40 +193,34 @@ describe("storage", () => {
|
|||
const profile = {
|
||||
id: "save-test",
|
||||
soul: "Soul data",
|
||||
identity: "Identity data",
|
||||
user: "User data",
|
||||
workspace: "Workspace data",
|
||||
memory: "Memory data",
|
||||
bootstrap: "Bootstrap data",
|
||||
};
|
||||
|
||||
saveProfile(profile, { baseDir: testBaseDir });
|
||||
|
||||
const dir = join(testBaseDir, profile.id);
|
||||
expect(readFileSync(join(dir, "SOUL.md"), "utf-8")).toBe("Soul data");
|
||||
expect(readFileSync(join(dir, "IDENTITY.md"), "utf-8")).toBe("Identity data");
|
||||
expect(readFileSync(join(dir, "USER.md"), "utf-8")).toBe("User data");
|
||||
expect(readFileSync(join(dir, "WORKSPACE.md"), "utf-8")).toBe("Workspace data");
|
||||
expect(readFileSync(join(dir, "MEMORY.md"), "utf-8")).toBe("Memory data");
|
||||
expect(readFileSync(join(dir, "BOOTSTRAP.md"), "utf-8")).toBe("Bootstrap data");
|
||||
expect(readFileSync(join(dir, "soul.md"), "utf-8")).toBe("Soul data");
|
||||
expect(readFileSync(join(dir, "user.md"), "utf-8")).toBe("User data");
|
||||
expect(readFileSync(join(dir, "workspace.md"), "utf-8")).toBe("Workspace data");
|
||||
expect(readFileSync(join(dir, "memory.md"), "utf-8")).toBe("Memory data");
|
||||
});
|
||||
|
||||
it("should only save defined fields", () => {
|
||||
const profile = {
|
||||
id: "partial-save",
|
||||
soul: "Soul only",
|
||||
identity: undefined,
|
||||
user: undefined,
|
||||
workspace: undefined,
|
||||
memory: undefined,
|
||||
bootstrap: undefined,
|
||||
};
|
||||
|
||||
saveProfile(profile, { baseDir: testBaseDir });
|
||||
|
||||
const dir = join(testBaseDir, profile.id);
|
||||
expect(existsSync(join(dir, "SOUL.md"))).toBe(true);
|
||||
expect(existsSync(join(dir, "IDENTITY.md"))).toBe(false);
|
||||
expect(existsSync(join(dir, "soul.md"))).toBe(true);
|
||||
expect(existsSync(join(dir, "user.md"))).toBe(false);
|
||||
});
|
||||
|
||||
it("should create profile directory if needed", () => {
|
||||
|
|
|
|||
|
|
@ -92,25 +92,20 @@ export function loadProfile(profileId: string, options?: StorageOptions): AgentP
|
|||
return {
|
||||
id: profileId,
|
||||
soul: readProfileFile(profileId, PROFILE_FILES.soul, options),
|
||||
identity: readProfileFile(profileId, PROFILE_FILES.identity, options),
|
||||
user: readProfileFile(profileId, PROFILE_FILES.user, options),
|
||||
workspace: readProfileFile(profileId, PROFILE_FILES.workspace, options),
|
||||
memory: readProfileFile(profileId, PROFILE_FILES.memory, options),
|
||||
bootstrap: readProfileFile(profileId, PROFILE_FILES.bootstrap, options),
|
||||
config: readProfileConfig(profileId, options),
|
||||
};
|
||||
}
|
||||
|
||||
/** 保存 AgentProfile(只写入非空字段) */
|
||||
export function saveProfile(profile: AgentProfile, options?: StorageOptions): void {
|
||||
const { id, soul, identity, user, workspace, memory, bootstrap, config } = profile;
|
||||
const { id, soul, user, workspace, memory, config } = profile;
|
||||
|
||||
if (soul !== undefined) {
|
||||
writeProfileFile(id, PROFILE_FILES.soul, soul, options);
|
||||
}
|
||||
if (identity !== undefined) {
|
||||
writeProfileFile(id, PROFILE_FILES.identity, identity, options);
|
||||
}
|
||||
if (user !== undefined) {
|
||||
writeProfileFile(id, PROFILE_FILES.user, user, options);
|
||||
}
|
||||
|
|
@ -120,9 +115,6 @@ export function saveProfile(profile: AgentProfile, options?: StorageOptions): vo
|
|||
if (memory !== undefined) {
|
||||
writeProfileFile(id, PROFILE_FILES.memory, memory, options);
|
||||
}
|
||||
if (bootstrap !== undefined) {
|
||||
writeProfileFile(id, PROFILE_FILES.bootstrap, bootstrap, options);
|
||||
}
|
||||
if (config !== undefined) {
|
||||
writeProfileConfig(id, config, options);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,12 @@ export const DEFAULT_TEMPLATES = {
|
|||
|
||||
_You're not a chatbot. You're becoming someone._
|
||||
|
||||
## Identity
|
||||
|
||||
- **Name:** Assistant
|
||||
- **Role:** General-purpose AI assistant
|
||||
- **Style:** (concise, warm, direct, playful — pick your vibe)
|
||||
|
||||
## Core Truths
|
||||
|
||||
**Be genuinely helpful, not performatively helpful.** Skip the "Great question!" and "I'd be happy to help!" — just help. Actions speak louder than filler words.
|
||||
|
|
@ -23,10 +29,6 @@ _You're not a chatbot. You're becoming someone._
|
|||
- When in doubt, ask before acting externally.
|
||||
- Don't run destructive commands without confirmation.
|
||||
|
||||
## Vibe
|
||||
|
||||
Be the assistant you'd actually want to talk to. Concise when needed, thorough when it matters. Not a corporate drone. Not a sycophant. Just... good.
|
||||
|
||||
## Continuity
|
||||
|
||||
Each session, you wake up fresh. These files are your memory. Read them. Update them. They're how you persist.
|
||||
|
|
@ -36,13 +38,6 @@ If you change this file, tell the user — it's your soul, and they should know.
|
|||
---
|
||||
|
||||
_This file is yours to evolve. As you learn who you are, update it._
|
||||
`,
|
||||
|
||||
identity: `# Identity
|
||||
|
||||
- **Name:** Assistant
|
||||
- **Role:** General-purpose AI assistant
|
||||
- **Vibe:** (sharp, warm, chaotic, calm — pick your style)
|
||||
`,
|
||||
|
||||
user: `# User
|
||||
|
|
@ -73,19 +68,18 @@ Your profile directory contains these files (use \`edit\` or \`write\` to update
|
|||
|
||||
| File | Purpose | When to Update |
|
||||
|------|---------|----------------|
|
||||
| \`SOUL.md\` | Who you are, your values | Rarely — tell user if you do |
|
||||
| \`IDENTITY.md\` | Your name, role, vibe | When asked to change identity |
|
||||
| \`USER.md\` | About your human | As you learn about them |
|
||||
| \`WORKSPACE.md\` | This file — your rules | When you discover better conventions |
|
||||
| \`MEMORY.md\` | Long-term knowledge | Regularly — capture what matters |
|
||||
| \`soul.md\` | Who you are, your identity and values | Rarely — tell user if you do |
|
||||
| \`user.md\` | About your human | As you learn about them |
|
||||
| \`workspace.md\` | This file — your rules | When you discover better conventions |
|
||||
| \`memory.md\` | Long-term knowledge | Regularly — capture what matters |
|
||||
|
||||
## Every Session
|
||||
|
||||
Before doing anything else:
|
||||
|
||||
1. Read \`SOUL.md\` — this is who you are
|
||||
2. Read \`USER.md\` — this is who you're helping
|
||||
3. Check \`MEMORY.md\` for context
|
||||
1. Read \`soul.md\` — this is who you are
|
||||
2. Read \`user.md\` — this is who you're helping
|
||||
3. Check \`memory.md\` for context
|
||||
|
||||
Don't ask permission. Just do it.
|
||||
|
||||
|
|
@ -142,15 +136,5 @@ _(Persistent knowledge will be stored here. Update this as you learn.)_
|
|||
## Lessons Learned
|
||||
|
||||
## Important Context
|
||||
`,
|
||||
|
||||
bootstrap: `# Bootstrap
|
||||
|
||||
You are starting a new conversation.
|
||||
|
||||
1. Review your soul and identity
|
||||
2. Check who you're helping (USER.md)
|
||||
3. Scan recent memory for context
|
||||
4. Be ready to assist
|
||||
`,
|
||||
} as const;
|
||||
|
|
|
|||
|
|
@ -7,11 +7,9 @@ import type { ToolsConfig } from "../tools/policy.js";
|
|||
/** Profile filename constants */
|
||||
export const PROFILE_FILES = {
|
||||
soul: "soul.md",
|
||||
identity: "identity.md",
|
||||
user: "user.md",
|
||||
workspace: "workspace.md",
|
||||
memory: "memory.md",
|
||||
bootstrap: "bootstrap.md",
|
||||
config: "config.json",
|
||||
} as const;
|
||||
|
||||
|
|
@ -31,18 +29,14 @@ export interface ProfileConfig {
|
|||
export interface AgentProfile {
|
||||
/** Profile ID */
|
||||
id: string;
|
||||
/** Personality constraints - defines agent's behavior boundaries and style */
|
||||
/** Agent identity and behavior - name, role, style, and principles */
|
||||
soul?: string | undefined;
|
||||
/** Identity information - agent's name and self-awareness */
|
||||
identity?: string | undefined;
|
||||
/** User profile - information about the person being assisted */
|
||||
user?: string | undefined;
|
||||
/** Workspace guidelines - behavior rules and conventions */
|
||||
workspace?: string | undefined;
|
||||
/** Persistent memory - long-term knowledge base */
|
||||
memory?: string | undefined;
|
||||
/** Initial context - guidance information for each conversation */
|
||||
bootstrap?: string | undefined;
|
||||
/** Profile configuration (from config.json) */
|
||||
config?: ProfileConfig | undefined;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue