跳到主要内容

DeepSeek Harness 本地聊天记忆:按来源保存聊天原文,关键词 + 向量检索,可选大模型重排与检索摘要。源码公开,仅限非商用

浏览文件
main

分支

config.js

39 行 · 2.7 KB历史下载
1import { normalizeProvider } from './models.js';
2import { DEFAULT_ORIGIN_RULES, normalizeRules } from './origin.js';
3import { UserError } from './errors.js';
4
5/** Tools whose text arguments count as the companion speaking (glob on the tool name). */
6export const DEFAULT_SPEAK_TOOLS = Object.freeze(['*send_message*', '*send_group_message*', '*send_private_message*', '*reply*']);
7/** Tools whose results are chat messages the companion read (glob on the tool name). */
8export const DEFAULT_HEAR_TOOLS = Object.freeze(['*unread*', '*recent_messages*', '*wait_for_messages*', '*message_history*', '*chat_history*', '*get_messages*']);
9
10const list = (value, fallback) => value === undefined ? [...fallback]
11 : Array.isArray(value) ? value.map(item => String(item).trim()).filter(Boolean)
12 : String(value).split(/[,,\s]+/).filter(Boolean);
13const bool = (value, fallback) => value === undefined ? fallback : value === true;
14
15export function normalizeSettings(input = {}) {
16 const setting = {
17 autoRecord: bool(input.autoRecord, true), autoRetrieve: bool(input.autoRetrieve, true), tools: bool(input.tools, true),
18 topK: input.topK ?? 6, maxContextChars: input.maxContextChars ?? 4000,
19 ownerIds: list(input.ownerIds, []),
20 // Legacy `shared: true` meant "this is a single-user instance": treat unknown sessions as the owner.
21 unknownOrigin: input.unknownOrigin ?? (input.shared === true ? 'owner' : 'isolated'),
22 shareGroups: bool(input.shareGroups, true), shareOwner: bool(input.shareOwner, true),
23 originRules: normalizeRules(input.originRules ?? DEFAULT_ORIGIN_RULES),
24 speakTools: list(input.speakTools, DEFAULT_SPEAK_TOOLS),
25 hearTools: list(input.hearTools, DEFAULT_HEAR_TOOLS),
26 // Use a suitable embedding model already installed in local Ollama when none is configured.
27 autoEmbedding: bool(input.autoEmbedding, true),
28 embedding: normalizeProvider(input.embedding),
29 reranker: normalizeProvider(input.reranker, 'reranker'),
30 };
31 if (!Number.isInteger(setting.topK) || setting.topK < 1 || setting.topK > 20) throw new UserError('每次检索片段数需为 1–20');
32 if (!Number.isInteger(setting.maxContextChars) || setting.maxContextChars < 300 || setting.maxContextChars > 20000)
33 throw new UserError('上下文预算需为 300–20000 字符');
34 if (setting.ownerIds.length > 10 || setting.ownerIds.some(id => !/^[\w.-]{1,64}$/.test(id))) throw new UserError('主人账号最多 10 个,只能含字母数字');
35 if (!['isolated', 'owner'].includes(setting.unknownOrigin)) throw new UserError('未识别会话的处理方式无效');
36 for (const name of ['speakTools', 'hearTools'])
37 if (setting[name].length > 20 || setting[name].some(glob => !/^[\w*.:-]{1,80}$/.test(glob))) throw new UserError('工具名格式不正确');
38 return setting;
39}