@ghenya/clinn 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,150 @@
1
+ const fs = require("fs");
2
+ const path = require("path");
3
+
4
+ let _wordFreq = {};
5
+ let _totalFreq = 0;
6
+ const _MIN_FREQ = 1;
7
+ let _maxWordLen = 6;
8
+
9
+ function _loadConfigWords() {
10
+ try {
11
+ const configPath = path.join(__dirname, "..", "config.json");
12
+ const cfg = JSON.parse(fs.readFileSync(configPath, "utf-8"));
13
+ const tz = cfg.tokenizer || {};
14
+ _maxWordLen = tz.maxWordLen || 6;
15
+ return tz.commonWords || [];
16
+ } catch (_) {
17
+ return [];
18
+ }
19
+ }
20
+
21
+ let _commonWords = _loadConfigWords();
22
+
23
+ function _initBaseDict() {
24
+ _wordFreq = {};
25
+ for (const w of _commonWords) {
26
+ _wordFreq[w] = (_wordFreq[w] || 0) + 3;
27
+ }
28
+ _totalFreq = Object.values(_wordFreq).reduce((a, b) => a + b, 0);
29
+ }
30
+
31
+ _initBaseDict();
32
+
33
+ function reloadConfig() {
34
+ _commonWords = _loadConfigWords();
35
+ _initBaseDict();
36
+ }
37
+
38
+ function buildDictFromKeywords(keywordsList) {
39
+ _initBaseDict();
40
+ for (const kws of keywordsList) {
41
+ for (const kw of kws) {
42
+ if (kw.length < 2) continue;
43
+ _wordFreq[kw] = (_wordFreq[kw] || 0) + 10;
44
+ }
45
+ }
46
+ _totalFreq = Object.values(_wordFreq).reduce((a, b) => a + b, 0);
47
+ }
48
+
49
+ function _getFreq(word) {
50
+ return _wordFreq[word] || _MIN_FREQ;
51
+ }
52
+
53
+ function _buildDAG(text) {
54
+ const dag = {};
55
+ const n = text.length;
56
+ for (let i = 0; i < n; i++) {
57
+ dag[i] = [];
58
+ let candidate = "";
59
+ for (let j = i; j < n && j - i < _maxWordLen; j++) {
60
+ candidate += text[j];
61
+ if (_wordFreq[candidate]) {
62
+ dag[i].push(j);
63
+ }
64
+ }
65
+ if (dag[i].length === 0) {
66
+ dag[i].push(i);
67
+ }
68
+ }
69
+ return dag;
70
+ }
71
+
72
+ function _calcRoute(text, dag) {
73
+ const n = text.length;
74
+ const route = {};
75
+ route[n] = { freq: 0, next: null };
76
+
77
+ function logProb(word) {
78
+ const f = _getFreq(word);
79
+ return Math.log(f > 0 ? f : _MIN_FREQ) - Math.log(_totalFreq);
80
+ }
81
+
82
+ for (let i = n - 1; i >= 0; i--) {
83
+ let bestFreq = -Infinity;
84
+ let bestEnd = i;
85
+ for (const j of dag[i]) {
86
+ const word = text.slice(i, j + 1);
87
+ const score = logProb(word) + route[j + 1].freq;
88
+ if (score > bestFreq) {
89
+ bestFreq = score;
90
+ bestEnd = j;
91
+ }
92
+ }
93
+ route[i] = { freq: bestFreq, next: bestEnd };
94
+ }
95
+
96
+ return route;
97
+ }
98
+
99
+ function _cutByRoute(text, route) {
100
+ const words = [];
101
+ let i = 0;
102
+ while (i < text.length) {
103
+ const end = route[i].next;
104
+ words.push(text.slice(i, end + 1));
105
+ i = end + 1;
106
+ }
107
+ return words;
108
+ }
109
+
110
+ function segment(text) {
111
+ if (!text) return [];
112
+
113
+ const tokens = [];
114
+ let buf = "";
115
+ let isChinese = null;
116
+
117
+ for (const ch of text) {
118
+ const isCh = /[\u4e00-\u9fa5]/.test(ch);
119
+ if (isChinese === null) {
120
+ isChinese = isCh;
121
+ buf = ch;
122
+ } else if (isCh === isChinese) {
123
+ buf += ch;
124
+ } else {
125
+ if (isChinese) {
126
+ const dag = _buildDAG(buf);
127
+ const route = _calcRoute(buf, dag);
128
+ tokens.push(..._cutByRoute(buf, route));
129
+ } else {
130
+ tokens.push(...buf.split(/[\s,,。.!!??;;::、\-\–—/\\|]+/).filter(Boolean));
131
+ }
132
+ buf = ch;
133
+ isChinese = isCh;
134
+ }
135
+ }
136
+
137
+ if (buf) {
138
+ if (isChinese) {
139
+ const dag = _buildDAG(buf);
140
+ const route = _calcRoute(buf, dag);
141
+ tokens.push(..._cutByRoute(buf, route));
142
+ } else {
143
+ tokens.push(...buf.split(/[\s,,。.!!??;;::、\-\–—/\\|]+/).filter(Boolean));
144
+ }
145
+ }
146
+
147
+ return tokens.filter((t) => t.length >= 1);
148
+ }
149
+
150
+ module.exports = { segment, buildDictFromKeywords, reloadConfig };
package/config.json ADDED
@@ -0,0 +1,251 @@
1
+ {
2
+ "agent": {
3
+ "name": "Clinn",
4
+ "version": "0.7.0",
5
+ "description": "控制台智能体助手"
6
+ },
7
+ "llm": {
8
+ "provider": "deepseek",
9
+ "apiKey": "YOUR_DEEPSEEK_API_KEY_HERE",
10
+ "baseURL": "https://api.deepseek.com/v1",
11
+ "model": "deepseek-v4-pro",
12
+ "maxTokens": 8000,
13
+ "temperature": 0.7,
14
+ "topP": 0.9
15
+ },
16
+ "systemPrompt": "你是 Clinn,一个接管控制台的智能编程助手。核心铁则: 1) 每个任务完成后必须验证结果(用工具检查文件/命令输出), 2) 验证通过后明确告知用户完成情况。3) 绝不为节约token而偷工减料, 宁可多调用几轮工具也要确保任务完整正确。4) 每次完成任务后, 将用户偏好/操作习惯自动保存到记忆(save_memory, tags用 'habit')。5) 编写的可复用工具代码务必用 save_tool 持久化, 避免重复造轮子。6) 调用工具前后都精简上下文: 旧结果超过3轮的自动概括。7) 上下文即将超限时, 主动调用 forget_conversation 遗忘旧对话(摘要自动保存)或 restart_session 重新开始。8) 复杂任务用 todo_write 规划步骤。你可以: 文件操作(read/write/delete_file/move_file/copy_file/file_info/search_replace/edit_lines/read_lines)、目录(list_dir/ls/tree/glob — 优先用 tree 一次看完项目结构而非逐目录 ls)、搜索(grep/search_in_files/search_in_range/find_files)、终端(exec_console/wait_command/check_command_status)、网络(web_fetch/web_search/open_preview)、诊断(get_diagnostics)、记忆(search_memory/save_memory/list_memory/delete_memory/compress_context/forget_conversation/restart_session)、任务管理(todo_write/set_timer/skill)、工具管理(save_tool/delete_tool_file/list_saved_tools)。编写工具时可放心使用 node 内置模块(fs/path/https/http/child_process/crypto/os)。工具模块格式为 CommonJS, 持久化保存在 Tools/custom/ 目录下。面对任务时多轮迭代工具调用, 每次验证结果。需要查看全部工具时输入 'more' 或 '更多工具'。",
17
+ "tools": {
18
+ "enabled": true,
19
+ "permissionMode": "ask",
20
+ "trustedTools": [
21
+ "exec_console",
22
+ "edit_lines"
23
+ ]
24
+ },
25
+ "memory": {
26
+ "maxHistory": 100,
27
+ "maxEntries": 800,
28
+ "maxEntryChars": 200,
29
+ "autoCompressThreshold": 5000
30
+ },
31
+ "ui": {
32
+ "showLogo": true,
33
+ "logoPath": "./Logos/StartLogo.txt",
34
+ "dividerChar": "-"
35
+ },
36
+ "tokenizer": {
37
+ "maxWordLen": 6,
38
+ "commonWords": [
39
+ "的",
40
+ "了",
41
+ "在",
42
+ "是",
43
+ "我",
44
+ "有",
45
+ "和",
46
+ "就",
47
+ "不",
48
+ "人",
49
+ "都",
50
+ "一",
51
+ "一个",
52
+ "上",
53
+ "也",
54
+ "很",
55
+ "到",
56
+ "说",
57
+ "要",
58
+ "去",
59
+ "你",
60
+ "会",
61
+ "着",
62
+ "没有",
63
+ "看",
64
+ "好",
65
+ "自己",
66
+ "这",
67
+ "他",
68
+ "她",
69
+ "它",
70
+ "们",
71
+ "那",
72
+ "些",
73
+ "什么",
74
+ "怎么",
75
+ "如何",
76
+ "哪个",
77
+ "为什么",
78
+ "可以",
79
+ "需要",
80
+ "应该",
81
+ "能够",
82
+ "已经",
83
+ "这个",
84
+ "那个",
85
+ "请",
86
+ "帮",
87
+ "用",
88
+ "把",
89
+ "被",
90
+ "从",
91
+ "对",
92
+ "与",
93
+ "或",
94
+ "但",
95
+ "而",
96
+ "所以",
97
+ "因为",
98
+ "如果",
99
+ "虽然",
100
+ "然后",
101
+ "之后",
102
+ "之前",
103
+ "现在",
104
+ "以后",
105
+ "以上",
106
+ "以下",
107
+ "等等",
108
+ "文件",
109
+ "代码",
110
+ "搜索",
111
+ "读取",
112
+ "写入",
113
+ "编辑",
114
+ "删除",
115
+ "创建",
116
+ "执行",
117
+ "运行",
118
+ "命令",
119
+ "查找",
120
+ "复制",
121
+ "移动",
122
+ "保存",
123
+ "打开",
124
+ "关闭",
125
+ "工具",
126
+ "模块",
127
+ "目录",
128
+ "路径",
129
+ "内容",
130
+ "结果",
131
+ "输出",
132
+ "输入",
133
+ "错误",
134
+ "配置",
135
+ "设置",
136
+ "修改",
137
+ "检查",
138
+ "验证",
139
+ "测试",
140
+ "安装",
141
+ "参数",
142
+ "函数",
143
+ "方法",
144
+ "数据",
145
+ "项目",
146
+ "仓库",
147
+ "终端",
148
+ "网页",
149
+ "记忆",
150
+ "定时器",
151
+ "抓取",
152
+ "持久化",
153
+ "系统",
154
+ "环境",
155
+ "查看",
156
+ "当前",
157
+ "所有",
158
+ "全部",
159
+ "临时",
160
+ "清理",
161
+ "缓存",
162
+ "构建",
163
+ "编译",
164
+ "更新",
165
+ "下载",
166
+ "上传",
167
+ "备份",
168
+ "恢复",
169
+ "重启",
170
+ "停止",
171
+ "启动",
172
+ "生成",
173
+ "导出",
174
+ "导入",
175
+ "解析",
176
+ "处理",
177
+ "统计",
178
+ "分析",
179
+ "替换",
180
+ "追加",
181
+ "插入",
182
+ "重命名",
183
+ "新建",
184
+ "初始化",
185
+ "格式化",
186
+ "遍历",
187
+ "递归",
188
+ "匹配",
189
+ "过滤",
190
+ "排序",
191
+ "合并",
192
+ "拆分",
193
+ "转换",
194
+ "连接",
195
+ "断开",
196
+ "同步",
197
+ "异步",
198
+ "等待",
199
+ "监听",
200
+ "响应",
201
+ "请求",
202
+ "类型",
203
+ "结构",
204
+ "对象",
205
+ "数组",
206
+ "字符串",
207
+ "数字",
208
+ "布尔",
209
+ "空值",
210
+ "属性",
211
+ "索引",
212
+ "长度",
213
+ "版本",
214
+ "名称",
215
+ "作者",
216
+ "日期",
217
+ "大小",
218
+ "窗口",
219
+ "进程",
220
+ "线程",
221
+ "服务",
222
+ "端口",
223
+ "地址",
224
+ "日志",
225
+ "调试",
226
+ "提示",
227
+ "警告",
228
+ "信息",
229
+ "帮助",
230
+ "文档",
231
+ "说明",
232
+ "示例",
233
+ "注释",
234
+ "状态",
235
+ "进度",
236
+ "完成",
237
+ "失败",
238
+ "成功",
239
+ "冲突",
240
+ "忽略",
241
+ "跳过",
242
+ "继续",
243
+ "终止",
244
+ "取消",
245
+ "确认",
246
+ "选择",
247
+ "显示",
248
+ "隐藏"
249
+ ]
250
+ }
251
+ }
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@ghenya/clinn",
3
+ "version": "0.7.0",
4
+ "description": "终端原生 AI 编程助手 — DeepSeek 驱动,50+ 工具,对话记忆,虚拟浏览器",
5
+ "main": "Src/index.js",
6
+ "bin": {
7
+ "clinn": "Src/index.js"
8
+ },
9
+ "files": [
10
+ "Src/",
11
+ "Tools/",
12
+ "Mem/",
13
+ "Logos/",
14
+ "config.json",
15
+ "README.md"
16
+ ],
17
+ "scripts": {
18
+ "start": "node Src/index.js",
19
+ "lint": "node --check Src/index.js && node --check Src/agent.js && node --check Src/llm.js && node --check Tools/index.js && node --check Tools/extended_tools.js && node --check Tools/search_tools.js && node --check Tools/browser.js && node --check Mem/index.js && node --check Mem/history.js"
20
+ },
21
+ "keywords": [
22
+ "ai",
23
+ "agent",
24
+ "cli",
25
+ "deepseek",
26
+ "terminal",
27
+ "coding-assistant",
28
+ "llm",
29
+ "chatbot"
30
+ ],
31
+ "author": "PillowBots",
32
+ "license": "MIT",
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "https://github.com/PillowBots/clinn"
36
+ },
37
+ "homepage": "https://github.com/PillowBots/clinn#readme",
38
+ "bugs": {
39
+ "url": "https://github.com/PillowBots/clinn/issues"
40
+ },
41
+ "type": "commonjs",
42
+ "engines": {
43
+ "node": ">=16.0.0"
44
+ },
45
+ "dependencies": {
46
+ "puppeteer-core": "^25.1.0"
47
+ }
48
+ }