Files
kurihada 5e32375f0e feat: 重构为 Monorepo 架构并实现 HTTP Server
架构变更:
- 采用 pnpm workspaces 实现 Monorepo 结构
- 将现有代码迁移到 packages/core
- 新增 packages/server HTTP 服务层

Server 功能:
- REST API: 会话管理、工具管理、配置管理
- WebSocket: 实时双向通信支持
- SSE: 服务端事件推送
- Hono + Bun 作为运行时

API 端点:
- GET/POST /api/sessions - 会话 CRUD
- GET/POST /api/sessions/:id/messages - 消息管理
- GET /api/sessions/:id/events - SSE 事件流
- WS /api/ws/:sessionId - WebSocket 连接
- GET/POST /api/tools - 工具管理
- GET/PUT /api/config - 配置管理
2025-12-12 10:42:20 +08:00

164 lines
4.9 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import { parseCommandSimple } from '../../../src/permission/bash-parser.js';
// 注意:parseBashCommand 需要初始化 tree-sitter wasm,在单元测试中使用 parseCommandSimple
describe('parseCommandSimple - 简单命令解析', () => {
describe('基本命令解析', () => {
it('解析单个命令', () => {
const result = parseCommandSimple('ls');
expect(result.name).toBe('ls');
expect(result.subcommand).toBeUndefined();
expect(result.args).toEqual([]);
expect(result.text).toBe('ls');
});
it('解析带子命令的命令', () => {
const result = parseCommandSimple('git status');
expect(result.name).toBe('git');
expect(result.subcommand).toBe('status');
expect(result.args).toEqual([]);
});
it('解析带参数的命令', () => {
const result = parseCommandSimple('git commit -m "message"');
expect(result.name).toBe('git');
expect(result.subcommand).toBe('commit');
expect(result.args).toContain('-m');
});
it('解析带 flag 前缀的子命令', () => {
const result = parseCommandSimple('rm -rf node_modules');
expect(result.name).toBe('rm');
// -rf 以 - 开头,所以 node_modules 是第一个非 flag 参数
expect(result.subcommand).toBe('node_modules');
expect(result.args).toContain('-rf');
});
});
describe('flag 和参数分离', () => {
it('短 flag 放入 args', () => {
const result = parseCommandSimple('ls -la');
expect(result.name).toBe('ls');
expect(result.subcommand).toBeUndefined();
expect(result.args).toContain('-la');
});
it('长 flag 放入 args', () => {
const result = parseCommandSimple('npm install --save-dev');
expect(result.name).toBe('npm');
expect(result.subcommand).toBe('install');
expect(result.args).toContain('--save-dev');
});
it('混合 flag 和参数', () => {
const result = parseCommandSimple('git checkout -b feature-branch');
expect(result.name).toBe('git');
expect(result.subcommand).toBe('checkout');
expect(result.args).toContain('-b');
expect(result.args).toContain('feature-branch');
});
});
describe('空白处理', () => {
it('处理前后空格', () => {
const result = parseCommandSimple(' git status ');
expect(result.name).toBe('git');
expect(result.subcommand).toBe('status');
});
it('处理多个空格分隔', () => {
const result = parseCommandSimple('git status -v');
expect(result.name).toBe('git');
expect(result.subcommand).toBe('status');
expect(result.args).toContain('-v');
});
it('空字符串返回空命令', () => {
const result = parseCommandSimple('');
expect(result.name).toBe('');
expect(result.subcommand).toBeUndefined();
expect(result.args).toEqual([]);
});
it('只有空格返回空命令', () => {
const result = parseCommandSimple(' ');
expect(result.name).toBe('');
});
});
describe('复杂命令', () => {
it('解析 git push 命令', () => {
const result = parseCommandSimple('git push origin main --force');
expect(result.name).toBe('git');
expect(result.subcommand).toBe('push');
expect(result.args).toContain('origin');
expect(result.args).toContain('main');
expect(result.args).toContain('--force');
});
it('解析 npm 命令', () => {
const result = parseCommandSimple('npm run build -- --watch');
expect(result.name).toBe('npm');
expect(result.subcommand).toBe('run');
expect(result.args).toContain('build');
});
it('解析 docker 命令', () => {
const result = parseCommandSimple('docker run -d -p 8080:80 nginx');
expect(result.name).toBe('docker');
expect(result.subcommand).toBe('run');
expect(result.args).toContain('-d');
expect(result.args).toContain('-p');
});
it('解析管道前的命令', () => {
// 简单解析不处理管道,只作为普通参数
const result = parseCommandSimple('cat file.txt');
expect(result.name).toBe('cat');
expect(result.subcommand).toBe('file.txt');
});
});
describe('保留原始文本', () => {
it('text 字段保留原始命令', () => {
const original = 'git commit -m "fix bug"';
const result = parseCommandSimple(original);
expect(result.text).toBe(original);
});
});
});
describe('ParsedCommand 结构', () => {
it('包含所有必要字段', () => {
const result = parseCommandSimple('git push');
expect(result).toHaveProperty('name');
expect(result).toHaveProperty('subcommand');
expect(result).toHaveProperty('args');
expect(result).toHaveProperty('text');
});
it('args 始终是数组', () => {
const result = parseCommandSimple('ls');
expect(Array.isArray(result.args)).toBe(true);
});
});