MCPcopy
hub / github.com/7836246/cursor2api / apiSaveConfig

Function apiSaveConfig

src/config-api.ts:41–162  ·  view source on GitHub ↗
(req: Request, res: Response)

Source from the content-addressed store, hash-verified

39 * 接收可热重载字段,合并写入 config.yaml,热重载由 fs.watch 自动触发
40 */
41export function apiSaveConfig(req: Request, res: Response): void {
42 const body = req.body as Record<string, unknown>;
43
44 // 基本类型校验
45 if (body.cursor_model !== undefined && typeof body.cursor_model !== 'string') {
46 res.status(400).json({ error: 'cursor_model must be a string' }); return;
47 }
48 if (body.timeout !== undefined && (typeof body.timeout !== 'number' || body.timeout <= 0)) {
49 res.status(400).json({ error: 'timeout must be a positive number' }); return;
50 }
51 if (body.max_auto_continue !== undefined && typeof body.max_auto_continue !== 'number') {
52 res.status(400).json({ error: 'max_auto_continue must be a number' }); return;
53 }
54 if (body.max_history_messages !== undefined && typeof body.max_history_messages !== 'number') {
55 res.status(400).json({ error: 'max_history_messages must be a number' }); return;
56 }
57 if (body.max_history_tokens !== undefined && typeof body.max_history_tokens !== 'number') {
58 res.status(400).json({ error: 'max_history_tokens must be a number' }); return;
59 }
60
61 try {
62 // 读取现有 yaml(如不存在则从空对象开始)
63 let raw: Record<string, unknown> = {};
64 if (existsSync('config.yaml')) {
65 raw = (parseYaml(readFileSync('config.yaml', 'utf-8')) as Record<string, unknown>) ?? {};
66 }
67
68 // 记录变更
69 const changes: string[] = [];
70
71 // 合并可热重载字段
72 if (body.cursor_model !== undefined && body.cursor_model !== raw.cursor_model) {
73 changes.push(`cursor_model: ${raw.cursor_model ?? '(unset)'} → ${body.cursor_model}`);
74 raw.cursor_model = body.cursor_model;
75 }
76 if (body.timeout !== undefined && body.timeout !== raw.timeout) {
77 changes.push(`timeout: ${raw.timeout ?? '(unset)'} → ${body.timeout}`);
78 raw.timeout = body.timeout;
79 }
80 if (body.max_auto_continue !== undefined && body.max_auto_continue !== raw.max_auto_continue) {
81 changes.push(`max_auto_continue: ${raw.max_auto_continue ?? '(unset)'} → ${body.max_auto_continue}`);
82 raw.max_auto_continue = body.max_auto_continue;
83 }
84 if (body.max_history_messages !== undefined && body.max_history_messages !== raw.max_history_messages) {
85 changes.push(`max_history_messages: ${raw.max_history_messages ?? '(unset)'} → ${body.max_history_messages}`);
86 raw.max_history_messages = body.max_history_messages;
87 }
88 if (body.max_history_tokens !== undefined && body.max_history_tokens !== raw.max_history_tokens) {
89 changes.push(`max_history_tokens: ${raw.max_history_tokens ?? '(unset)'} → ${body.max_history_tokens}`);
90 raw.max_history_tokens = body.max_history_tokens;
91 }
92 if (body.thinking !== undefined) {
93 const t = body.thinking as { enabled: boolean | null } | null;
94 const oldVal = JSON.stringify(raw.thinking);
95 if (t === null || t?.enabled === null) {
96 // null = 跟随客户端:从 yaml 中删除 thinking 节
97 if (raw.thinking !== undefined) {
98 changes.push(`thinking: ${oldVal} → (跟随客户端)`);

Callers

nothing calls this directly

Calls 5

pushMethod · 0.80
logMethod · 0.80
errorMethod · 0.80
jsonMethod · 0.45
statusMethod · 0.45

Tested by

no test coverage detected