mirror of
https://github.com/MoonshotAI/kimi-code.git
synced 2026-07-20 22:54:26 +00:00
* feat(agent-core): support plugin slash commands * feat(node-sdk): expose listPluginCommands * feat(kimi-code): register and dispatch plugin slash commands * chore: add changeset for plugin commands * feat(agent-core): activate plugin commands server-side * feat(node-sdk): add activatePluginCommand * feat(kimi-code): render plugin command activations compactly * feat(agent-core): recurse plugin command directories and preserve namespace * fix(kimi-code): parse nested plugin command names * fix(agent-core): update prompt metadata for plugin command turns * fix(kimi-code): replay plugin command turns as command cards * fix: treat plugin-command origins as real user prompts in undo * fix(kimi-code): guard model-empty and clear plugin command render ids * fix: propagate plugin_command to web and vis turn projectors * fix(kimi-code): refresh plugin commands through auth flow * fix(kimi-web): render plugin command cards in chat pane * fix(kimi-web): render plugin command card in desktop chat view * fix(kimi-code): treat slash-activation cards as transcript turn boundaries * fix(kimi-code): count slash-activation entries when trimming transcript turns * fix(kimi-code): preserve plugin command args in undo selector
65 lines
2.2 KiB
TypeScript
65 lines
2.2 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
|
|
import { expandCommandArguments, parseCommandText } from '../../src/plugin/commands';
|
|
|
|
describe('parseCommandText', () => {
|
|
it('parses frontmatter description and body', () => {
|
|
const def = parseCommandText({
|
|
text: '---\ndescription: Deploy to Vercel\n---\nDeploy this. Args: $ARGUMENTS',
|
|
commandPath: '/p/commands/deploy.md',
|
|
pluginId: 'my-plugin',
|
|
});
|
|
expect(def).toEqual({
|
|
pluginId: 'my-plugin',
|
|
name: 'deploy',
|
|
description: 'Deploy to Vercel',
|
|
body: 'Deploy this. Args: $ARGUMENTS',
|
|
path: '/p/commands/deploy.md',
|
|
});
|
|
});
|
|
|
|
it('uses frontmatter name over the filename', () => {
|
|
const def = parseCommandText({
|
|
text: '---\nname: ship\ndescription: Ship it\n---\nbody',
|
|
commandPath: '/p/commands/deploy.md',
|
|
pluginId: 'p',
|
|
});
|
|
expect(def.name).toBe('ship');
|
|
});
|
|
|
|
it('falls back to filename for name and first body line for description', () => {
|
|
const def = parseCommandText({
|
|
text: 'Deploy this project to Vercel.\n\nMore details.',
|
|
commandPath: '/p/commands/deploy.md',
|
|
pluginId: 'p',
|
|
});
|
|
expect(def.name).toBe('deploy');
|
|
expect(def.description).toBe('Deploy this project to Vercel.');
|
|
expect(def.body).toBe('Deploy this project to Vercel.\n\nMore details.');
|
|
});
|
|
|
|
it('handles an empty body with a default description', () => {
|
|
const def = parseCommandText({
|
|
text: '',
|
|
commandPath: '/p/commands/x.md',
|
|
pluginId: 'p',
|
|
});
|
|
expect(def.name).toBe('x');
|
|
expect(def.description).toBe('No description provided.');
|
|
expect(def.body).toBe('');
|
|
});
|
|
});
|
|
|
|
describe('expandCommandArguments', () => {
|
|
it('replaces $ARGUMENTS with the typed args', () => {
|
|
expect(expandCommandArguments('Deploy $ARGUMENTS now', 'prod')).toBe('Deploy prod now');
|
|
});
|
|
|
|
it('appends args when there is no placeholder', () => {
|
|
expect(expandCommandArguments('Deploy now', 'prod')).toBe('Deploy now\n\nARGUMENTS: prod');
|
|
});
|
|
|
|
it('leaves the body unchanged when there is no placeholder and no args', () => {
|
|
expect(expandCommandArguments('Deploy now', '')).toBe('Deploy now');
|
|
});
|
|
});
|