From 0ce0072cb44ea2bd3a7ca9c54d141c150f0bbb77 Mon Sep 17 00:00:00 2001 From: happy wang Date: Tue, 26 May 2026 17:50:38 +0800 Subject: [PATCH] fix(agent-core): resolve user skills from OS home directory, not kimi home (#72) * fix(agent-core): resolve user skills from OS home directory, not kimi home KimiCore incorrectly used the kimi home directory (e.g. ~/.kimi-code) as userHomeDir, causing the skill scanner to look for user skills under ~/.kimi-code/.agents/skills/ instead of ~/.agents/skills/. Only the builtin mcp-config skill was found. Fix by always setting userHomeDir to homedir() (the actual OS home), independent of the homeDir / KIMI_CODE_HOME options that control where session data is stored. * chore: add changeset for skill user home dir fix * test(node-sdk): align SDK skill test with OS home resolution fix * Apply suggestion from @liruifengv Signed-off-by: liruifengv --------- Signed-off-by: liruifengv Co-authored-by: liruifengv --- .changeset/fix-skill-user-home-dir.md | 6 ++++++ packages/agent-core/src/rpc/core-impl.ts | 3 +-- .../agent-core/test/harness/skill-session.test.ts | 12 ++++++------ packages/node-sdk/test/session-skills.test.ts | 6 +++--- 4 files changed, 16 insertions(+), 11 deletions(-) create mode 100644 .changeset/fix-skill-user-home-dir.md diff --git a/.changeset/fix-skill-user-home-dir.md b/.changeset/fix-skill-user-home-dir.md new file mode 100644 index 000000000..80f073191 --- /dev/null +++ b/.changeset/fix-skill-user-home-dir.md @@ -0,0 +1,6 @@ +--- +"@moonshot-ai/agent-core": patch +"@moonshot-ai/kimi-code": patch +--- + +Fix user skills in ~/.agents/ not being loaded. diff --git a/packages/agent-core/src/rpc/core-impl.ts b/packages/agent-core/src/rpc/core-impl.ts index c25a1c759..e79d11a4e 100644 --- a/packages/agent-core/src/rpc/core-impl.ts +++ b/packages/agent-core/src/rpc/core-impl.ts @@ -114,9 +114,8 @@ export class KimiCore implements PromisableMethods { protected readonly rpcClient: CoreRPCClient, options: KimiCoreOptions = {}, ) { - const explicitHomeDir = options.homeDir ?? process.env['KIMI_CODE_HOME']; this.homeDir = resolveKimiHome(options.homeDir); - this.userHomeDir = explicitHomeDir ?? homedir(); + this.userHomeDir = homedir(); this.configPath = resolveConfigPath({ homeDir: this.homeDir, configPath: options.configPath, diff --git a/packages/agent-core/test/harness/skill-session.test.ts b/packages/agent-core/test/harness/skill-session.test.ts index 8cb0c1612..6c20abd75 100644 --- a/packages/agent-core/test/harness/skill-session.test.ts +++ b/packages/agent-core/test/harness/skill-session.test.ts @@ -100,7 +100,7 @@ describe('HarnessAPI session skills', () => { expect(JSON.stringify(skills)).not.toContain('Your tool list contains one synthetic tool'); }); - it('uses the explicit core home as user skill home instead of the process home', async () => { + it('resolves user skills from the OS home directory, not from the kimi home', async () => { const processHome = join(tmp, 'process-home'); vi.stubEnv('HOME', processHome); await writeUserSkill(processHome, 'real-home-only', 'Real home skill'); @@ -110,11 +110,11 @@ describe('HarnessAPI session skills', () => { const names = new Set((await rpc.listSkills({ sessionId: created.id })).map((skill) => skill.name)); - expect(names.has('sandbox-only')).toBe(true); - expect(names.has('real-home-only')).toBe(false); + expect(names.has('real-home-only')).toBe(true); + expect(names.has('sandbox-only')).toBe(false); }); - it('uses KIMI_CODE_HOME as user skill home when core home comes from env', async () => { + it('resolves user skills from the OS home directory even when KIMI_CODE_HOME is set', async () => { const processHome = join(tmp, 'env-process-home'); vi.stubEnv('HOME', processHome); vi.stubEnv('KIMI_CODE_HOME', homeDir); @@ -125,8 +125,8 @@ describe('HarnessAPI session skills', () => { const names = new Set((await rpc.listSkills({ sessionId: created.id })).map((skill) => skill.name)); - expect(names.has('env-sandbox-only')).toBe(true); - expect(names.has('env-real-home-only')).toBe(false); + expect(names.has('env-real-home-only')).toBe(true); + expect(names.has('env-sandbox-only')).toBe(false); }); it('activates an inline skill through core and records display origin metadata', async () => { diff --git a/packages/node-sdk/test/session-skills.test.ts b/packages/node-sdk/test/session-skills.test.ts index 5be7bb2ec..6f785bb40 100644 --- a/packages/node-sdk/test/session-skills.test.ts +++ b/packages/node-sdk/test/session-skills.test.ts @@ -192,7 +192,7 @@ describe('Session skills', () => { } }); - it('uses KIMI_CODE_HOME as the user skill home through the SDK harness', async () => { + it('resolves user skills from the OS home directory, independently of KIMI_CODE_HOME', async () => { const homeDir = await makeTempDir(tempDirs, 'kimi-sdk-skills-home-'); const processHome = await makeTempDir(tempDirs, 'kimi-sdk-skills-process-home-'); const workDir = await makeTempDir(tempDirs, 'kimi-sdk-skills-work-'); @@ -206,8 +206,8 @@ describe('Session skills', () => { const session = await harness.createSession({ id: 'ses_sdk_skill_env_home', workDir }); const names = new Set((await session.listSkills()).map((skill) => skill.name)); - expect(names.has('sdk-sandbox-only')).toBe(true); - expect(names.has('sdk-real-home-only')).toBe(false); + expect(names.has('sdk-real-home-only')).toBe(true); + expect(names.has('sdk-sandbox-only')).toBe(false); } finally { await harness.close(); }