zhitalk 0.0.0 → 0.0.2
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.
- package/CLAUDE.md +98 -0
- package/README.md +18 -1
- package/dist/agent/agent.d.ts +24 -0
- package/dist/agent/agent.js +345 -0
- package/dist/agent/cli.d.ts +1 -0
- package/dist/agent/cli.js +185 -0
- package/dist/agent/colors.d.ts +19 -0
- package/dist/agent/colors.js +81 -0
- package/dist/agent/commands.d.ts +7 -0
- package/dist/agent/commands.js +69 -0
- package/dist/agent/config.d.ts +38 -0
- package/dist/agent/config.js +116 -0
- package/dist/agent/context.d.ts +3 -0
- package/dist/agent/context.js +107 -0
- package/dist/agent/db.d.ts +21 -0
- package/dist/agent/db.js +159 -0
- package/dist/agent/hooks.d.ts +27 -0
- package/dist/agent/hooks.js +115 -0
- package/dist/agent/mcp/client.d.ts +25 -0
- package/dist/agent/mcp/client.js +113 -0
- package/dist/agent/mcp/index.d.ts +4 -0
- package/dist/agent/mcp/index.js +27 -0
- package/dist/agent/mcp/wrapper.d.ts +7 -0
- package/dist/agent/mcp/wrapper.js +25 -0
- package/dist/agent/model.d.ts +5 -0
- package/dist/agent/model.js +31 -0
- package/dist/agent/permission/dangerous-path.json +115 -0
- package/dist/agent/permission/exec.d.ts +11 -0
- package/dist/agent/permission/exec.js +34 -0
- package/dist/agent/permission/is-dangerous-path.d.ts +1 -0
- package/dist/agent/permission/is-dangerous-path.js +53 -0
- package/dist/agent/permission/is-safe-domains.d.ts +1 -0
- package/dist/agent/permission/is-safe-domains.js +142 -0
- package/dist/agent/permission/network.d.ts +8 -0
- package/dist/agent/permission/network.js +14 -0
- package/dist/agent/permission/read.d.ts +9 -0
- package/dist/agent/permission/read.js +17 -0
- package/dist/agent/permission/util.d.ts +11 -0
- package/dist/agent/permission/util.js +160 -0
- package/dist/agent/permission/write.d.ts +11 -0
- package/dist/agent/permission/write.js +21 -0
- package/dist/agent/prompt.d.ts +1 -0
- package/dist/agent/prompt.js +50 -0
- package/dist/agent/skills.d.ts +8 -0
- package/dist/agent/skills.js +91 -0
- package/dist/agent/tools/agent_tool.d.ts +3 -0
- package/dist/agent/tools/agent_tool.js +44 -0
- package/dist/agent/tools/exec_tool.d.ts +3 -0
- package/dist/agent/tools/exec_tool.js +28 -0
- package/dist/agent/tools/load_skill_tool.d.ts +3 -0
- package/dist/agent/tools/load_skill_tool.js +15 -0
- package/dist/agent/tools/memory_create_tool.d.ts +6 -0
- package/dist/agent/tools/memory_create_tool.js +37 -0
- package/dist/agent/tools/memory_delete_tool.d.ts +3 -0
- package/dist/agent/tools/memory_delete_tool.js +28 -0
- package/dist/agent/tools/memory_retrieve_tool.d.ts +4 -0
- package/dist/agent/tools/memory_retrieve_tool.js +24 -0
- package/dist/agent/tools/profile_update_tool.d.ts +3 -0
- package/dist/agent/tools/profile_update_tool.js +50 -0
- package/dist/agent/tools/read_file_tool.d.ts +3 -0
- package/dist/agent/tools/read_file_tool.js +16 -0
- package/dist/agent/tools/run_js_tool.d.ts +3 -0
- package/dist/agent/tools/run_js_tool.js +36 -0
- package/dist/agent/tools/run_py_tool.d.ts +3 -0
- package/dist/agent/tools/run_py_tool.js +27 -0
- package/dist/agent/tools/search.d.ts +3 -0
- package/dist/agent/tools/search.js +10 -0
- package/dist/agent/tools/web_fetch_tool.d.ts +3 -0
- package/dist/agent/tools/web_fetch_tool.js +33 -0
- package/dist/agent/tools/web_search_tool.d.ts +3 -0
- package/dist/agent/tools/web_search_tool.js +38 -0
- package/dist/agent/tools/write_file_tool.d.ts +4 -0
- package/dist/agent/tools/write_file_tool.js +15 -0
- package/dist/agent/tools.d.ts +8 -0
- package/dist/agent/tools.js +193 -0
- package/dist/agent/utils.d.ts +2 -0
- package/dist/agent/utils.js +30 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +72 -0
- package/dist/install.d.ts +1 -0
- package/dist/install.js +108 -0
- package/package.json +43 -6
- package/index.js +0 -1
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare function initColors(): Promise<void>;
|
|
2
|
+
export declare const color: {
|
|
3
|
+
banner: (text: string) => string;
|
|
4
|
+
userPrefix: () => string;
|
|
5
|
+
aiPrefix: () => string;
|
|
6
|
+
goodbye: (text: string) => string;
|
|
7
|
+
cancelled: (text: string) => string;
|
|
8
|
+
error: (text: string) => string;
|
|
9
|
+
toolTag: () => string;
|
|
10
|
+
toolName: (name: string) => string;
|
|
11
|
+
toolAction: () => string;
|
|
12
|
+
toolArg: (arg: string) => string;
|
|
13
|
+
gray: (text: string) => string;
|
|
14
|
+
tokenInfo: (text: string) => string;
|
|
15
|
+
warn: (text: string) => string;
|
|
16
|
+
info: (text: string) => string;
|
|
17
|
+
good: (text: string) => string;
|
|
18
|
+
};
|
|
19
|
+
export declare function formatToolLog(name: string, detail?: string): string;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.color = void 0;
|
|
37
|
+
exports.initColors = initColors;
|
|
38
|
+
exports.formatToolLog = formatToolLog;
|
|
39
|
+
let _chalk = null;
|
|
40
|
+
async function initColors() {
|
|
41
|
+
const mod = (await Promise.resolve().then(() => __importStar(require('chalk'))));
|
|
42
|
+
_chalk = mod.default;
|
|
43
|
+
}
|
|
44
|
+
function createPlainFallback() {
|
|
45
|
+
const handler = {
|
|
46
|
+
get: () => createPlainFallback(),
|
|
47
|
+
apply: (_target, _thisArg, args) => args[0] ?? '',
|
|
48
|
+
};
|
|
49
|
+
const fn = (...args) => args[0] ?? '';
|
|
50
|
+
return new Proxy(fn, handler);
|
|
51
|
+
}
|
|
52
|
+
function ck() {
|
|
53
|
+
if (!_chalk) {
|
|
54
|
+
return createPlainFallback();
|
|
55
|
+
}
|
|
56
|
+
return _chalk;
|
|
57
|
+
}
|
|
58
|
+
exports.color = {
|
|
59
|
+
banner: (text) => ck().cyanBright.bold(text),
|
|
60
|
+
userPrefix: () => ck().greenBright.bold('You: '),
|
|
61
|
+
aiPrefix: () => ck().cyanBright.bold('AI: '),
|
|
62
|
+
goodbye: (text) => ck().yellowBright(text),
|
|
63
|
+
cancelled: (text) => ck().yellowBright.bold(text),
|
|
64
|
+
error: (text) => ck().redBright.bold(text),
|
|
65
|
+
toolTag: () => ck().magentaBright('[Tool]'),
|
|
66
|
+
toolName: (name) => ck().yellowBright(name),
|
|
67
|
+
toolAction: () => ck().gray('called:'),
|
|
68
|
+
toolArg: (arg) => ck().cyan(arg),
|
|
69
|
+
gray: (text) => ck().gray(text),
|
|
70
|
+
tokenInfo: (text) => ck().gray(text),
|
|
71
|
+
warn: (text) => ck().yellow(text),
|
|
72
|
+
info: (text) => ck().blueBright(text),
|
|
73
|
+
good: (text) => ck().greenBright(text),
|
|
74
|
+
};
|
|
75
|
+
function formatToolLog(name, detail) {
|
|
76
|
+
const parts = [exports.color.toolTag(), exports.color.toolName(name), exports.color.toolAction()];
|
|
77
|
+
if (detail) {
|
|
78
|
+
parts.push(exports.color.toolArg(detail));
|
|
79
|
+
}
|
|
80
|
+
return '\n' + parts.join(' ');
|
|
81
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.commands = exports.threadId = void 0;
|
|
7
|
+
const crypto_1 = require("crypto");
|
|
8
|
+
const cli_table3_1 = __importDefault(require("cli-table3"));
|
|
9
|
+
const colors_1 = require("./colors");
|
|
10
|
+
const db_1 = require("./db");
|
|
11
|
+
const agent_1 = require("./agent");
|
|
12
|
+
exports.threadId = (0, crypto_1.randomUUID)();
|
|
13
|
+
exports.commands = new Map();
|
|
14
|
+
exports.commands.set('new', {
|
|
15
|
+
name: 'new',
|
|
16
|
+
description: 'Start a new chat session',
|
|
17
|
+
execute() {
|
|
18
|
+
exports.threadId = (0, crypto_1.randomUUID)();
|
|
19
|
+
console.log(colors_1.color.goodbye(`\nNew session started ${exports.threadId}.\n`));
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
exports.commands.set('rewind', {
|
|
23
|
+
name: 'rewind',
|
|
24
|
+
description: 'Restore a chat session by thread_id',
|
|
25
|
+
execute(args) {
|
|
26
|
+
const id = args[0];
|
|
27
|
+
if (!id) {
|
|
28
|
+
console.log(colors_1.color.error('\nError: please provide a thread_id. Usage: /rewind <thread_id>\n'));
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (!(0, db_1.threadIdExists)(id)) {
|
|
32
|
+
console.log(colors_1.color.error(`\nError: thread_id "${id}" not found.\n`));
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
exports.threadId = id;
|
|
36
|
+
console.log(colors_1.color.goodbye(`\nRestored session ${exports.threadId}.\n`));
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
exports.commands.set('sessions', {
|
|
40
|
+
name: 'sessions',
|
|
41
|
+
description: 'List recent chat sessions',
|
|
42
|
+
execute() {
|
|
43
|
+
const sessions = (0, db_1.listRecentSessions)();
|
|
44
|
+
if (sessions.length === 0) {
|
|
45
|
+
console.log('\n暂无聊天记录\n');
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const table = new cli_table3_1.default({
|
|
49
|
+
head: ['thread_id', '最后用户输入的问题', '时间'],
|
|
50
|
+
});
|
|
51
|
+
for (const s of sessions) {
|
|
52
|
+
table.push([s.thread_id, s.last_question, s.last_ts]);
|
|
53
|
+
}
|
|
54
|
+
console.log('\n' + table.toString() + '\n');
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
exports.commands.set('compact', {
|
|
58
|
+
name: 'compact',
|
|
59
|
+
description: 'Compress context for the current session',
|
|
60
|
+
async execute() {
|
|
61
|
+
const result = await (0, agent_1.compressContext)(exports.threadId);
|
|
62
|
+
if (result.didCompress) {
|
|
63
|
+
console.log(colors_1.color.goodbye(`\nContext compressed (count: ${result.count}).\n`));
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
console.log('\nNo context to compress.\n');
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export declare const WORKSPACE_DIR: string;
|
|
2
|
+
export declare const CONFIG_PATH: string;
|
|
3
|
+
interface ModelConfig {
|
|
4
|
+
model: string;
|
|
5
|
+
apiKey: string;
|
|
6
|
+
baseURL: string;
|
|
7
|
+
}
|
|
8
|
+
export interface HookConfig {
|
|
9
|
+
matcher: string;
|
|
10
|
+
command: string;
|
|
11
|
+
}
|
|
12
|
+
export interface HooksConfig {
|
|
13
|
+
hooks: {
|
|
14
|
+
PreToolUse?: HookConfig[];
|
|
15
|
+
PostToolUse?: HookConfig[];
|
|
16
|
+
SessionStart?: HookConfig[];
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export interface McpServerConfig {
|
|
20
|
+
command?: string;
|
|
21
|
+
args?: string[];
|
|
22
|
+
env?: Record<string, string>;
|
|
23
|
+
url?: string;
|
|
24
|
+
headers?: Record<string, string>;
|
|
25
|
+
}
|
|
26
|
+
interface ZhitalkConfig {
|
|
27
|
+
model?: ModelConfig;
|
|
28
|
+
env?: Record<string, string>;
|
|
29
|
+
hooks?: HooksConfig['hooks'];
|
|
30
|
+
mcpServers?: Record<string, McpServerConfig>;
|
|
31
|
+
}
|
|
32
|
+
export declare function loadConfig(): ZhitalkConfig;
|
|
33
|
+
export declare function getModelConfig(): ModelConfig;
|
|
34
|
+
export declare function getEnv(key: string): string | undefined;
|
|
35
|
+
export declare function getHooksConfig(): HooksConfig;
|
|
36
|
+
export declare function getMCPServerConfig(): Record<string, McpServerConfig>;
|
|
37
|
+
export declare function clearConfigCache(): void;
|
|
38
|
+
export {};
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.CONFIG_PATH = exports.WORKSPACE_DIR = void 0;
|
|
37
|
+
exports.loadConfig = loadConfig;
|
|
38
|
+
exports.getModelConfig = getModelConfig;
|
|
39
|
+
exports.getEnv = getEnv;
|
|
40
|
+
exports.getHooksConfig = getHooksConfig;
|
|
41
|
+
exports.getMCPServerConfig = getMCPServerConfig;
|
|
42
|
+
exports.clearConfigCache = clearConfigCache;
|
|
43
|
+
const fs = __importStar(require("fs"));
|
|
44
|
+
const path = __importStar(require("path"));
|
|
45
|
+
const os = __importStar(require("os"));
|
|
46
|
+
exports.WORKSPACE_DIR = path.join(os.homedir(), '.zhitalk');
|
|
47
|
+
exports.CONFIG_PATH = path.join(exports.WORKSPACE_DIR, 'zhitalk.json');
|
|
48
|
+
let cachedConfig = null;
|
|
49
|
+
function loadConfig() {
|
|
50
|
+
if (cachedConfig) {
|
|
51
|
+
return cachedConfig;
|
|
52
|
+
}
|
|
53
|
+
if (!fs.existsSync(exports.CONFIG_PATH)) {
|
|
54
|
+
throw new Error(`找不到配置文件 ${exports.CONFIG_PATH}\n\n请创建该文件并配置相关信息,例如:\n{\n "model": {\n "model": "kimi-k2.6",\n "apiKey": "your-api-key",\n "baseURL": "https://api.moonshot.cn/v1"\n },\n "env": {\n "TAVILY_API_KEY": "your-tavily-api-key"\n }\n}`);
|
|
55
|
+
}
|
|
56
|
+
let config;
|
|
57
|
+
try {
|
|
58
|
+
const content = fs.readFileSync(exports.CONFIG_PATH, 'utf-8');
|
|
59
|
+
config = JSON.parse(content);
|
|
60
|
+
}
|
|
61
|
+
catch (e) {
|
|
62
|
+
throw new Error(`配置文件 ${exports.CONFIG_PATH} 解析失败:${e instanceof Error ? e.message : String(e)}`);
|
|
63
|
+
}
|
|
64
|
+
cachedConfig = config;
|
|
65
|
+
return config;
|
|
66
|
+
}
|
|
67
|
+
function getModelConfig() {
|
|
68
|
+
const config = loadConfig();
|
|
69
|
+
if (!config.model || typeof config.model !== 'object') {
|
|
70
|
+
throw new Error(`配置文件 ${exports.CONFIG_PATH} 中缺少 model 对象,请参考 https://zhitalk.chat/#config 修改配置`);
|
|
71
|
+
}
|
|
72
|
+
if (!config.model.model) {
|
|
73
|
+
throw new Error(`配置文件 ${exports.CONFIG_PATH} 中缺少 model.model 字段,请参考 https://zhitalk.chat/#config 修改配置`);
|
|
74
|
+
}
|
|
75
|
+
if (!config.model.apiKey) {
|
|
76
|
+
throw new Error(`配置文件 ${exports.CONFIG_PATH} 中缺少 model.apiKey 字段,请参考 https://zhitalk.chat/#config 修改配置`);
|
|
77
|
+
}
|
|
78
|
+
if (!config.model.baseURL) {
|
|
79
|
+
throw new Error(`配置文件 ${exports.CONFIG_PATH} 中缺少 model.baseURL 字段,请参考 https://zhitalk.chat/#config 修改配置`);
|
|
80
|
+
}
|
|
81
|
+
return config.model;
|
|
82
|
+
}
|
|
83
|
+
function getEnv(key) {
|
|
84
|
+
const config = loadConfig();
|
|
85
|
+
return config.env?.[key];
|
|
86
|
+
}
|
|
87
|
+
function getHooksConfig() {
|
|
88
|
+
try {
|
|
89
|
+
const config = loadConfig();
|
|
90
|
+
return { hooks: config.hooks || {} };
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return { hooks: {} };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function getMCPServerConfig() {
|
|
97
|
+
try {
|
|
98
|
+
const content = fs.readFileSync(exports.CONFIG_PATH, 'utf-8');
|
|
99
|
+
const parsed = JSON.parse(content);
|
|
100
|
+
if (!parsed.mcpServers || typeof parsed.mcpServers !== 'object') {
|
|
101
|
+
// console.warn('[MCP] zhitalk.json missing "mcpServers" field, skipping')
|
|
102
|
+
return {};
|
|
103
|
+
}
|
|
104
|
+
return parsed.mcpServers;
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
if (err.code === 'ENOENT') {
|
|
108
|
+
return {};
|
|
109
|
+
}
|
|
110
|
+
console.warn(`[MCP] Failed to load zhitalk.json: ${err.message}, skipping`);
|
|
111
|
+
return {};
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
function clearConfigCache() {
|
|
115
|
+
cachedConfig = null;
|
|
116
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getModelContextLimit = getModelContextLimit;
|
|
4
|
+
exports.compressMessages = compressMessages;
|
|
5
|
+
const messages_1 = require("@langchain/core/messages");
|
|
6
|
+
const model_1 = require("./model");
|
|
7
|
+
const config_1 = require("./config");
|
|
8
|
+
const MODEL_CONTEXT_LIMITS = {
|
|
9
|
+
// Moonshot / Kimi
|
|
10
|
+
'moonshot-v1-8k': 8192,
|
|
11
|
+
'moonshot-v1-32k': 32768,
|
|
12
|
+
'moonshot-v1-128k': 131072,
|
|
13
|
+
'kimi-k2.6': 256000,
|
|
14
|
+
// DeepSeek
|
|
15
|
+
'deepseek-chat': 1048576,
|
|
16
|
+
'deepseek-reasoner': 1048576,
|
|
17
|
+
'deepseek-v3': 65536,
|
|
18
|
+
'deepseek-v3.1': 131072,
|
|
19
|
+
'deepseek-v4': 1048576,
|
|
20
|
+
'deepseek-r1': 65536,
|
|
21
|
+
// MiniMax
|
|
22
|
+
'minimax-text-01': 1048576,
|
|
23
|
+
'minimax-m1': 1048576,
|
|
24
|
+
'minimax-m3': 1048576,
|
|
25
|
+
// GLM (Zhipu)
|
|
26
|
+
'glm-4': 131072,
|
|
27
|
+
'glm-4-plus': 131072,
|
|
28
|
+
'glm-4-air': 131072,
|
|
29
|
+
'glm-4-flash': 131072,
|
|
30
|
+
'glm-4v': 131072,
|
|
31
|
+
// Qwen (Alibaba)
|
|
32
|
+
'qwen-max': 32768,
|
|
33
|
+
'qwen-plus': 131072,
|
|
34
|
+
'qwen-plus-2025-07-28': 1048576,
|
|
35
|
+
'qwen-turbo': 1048576,
|
|
36
|
+
'qwen-long': 10485760,
|
|
37
|
+
// Xiaomi MiMo
|
|
38
|
+
'mimo-7b': 32768,
|
|
39
|
+
'mimo-v2.5': 1048576,
|
|
40
|
+
};
|
|
41
|
+
function getModelContextLimit() {
|
|
42
|
+
const modelName = (0, config_1.getModelConfig)().model || '';
|
|
43
|
+
return MODEL_CONTEXT_LIMITS[modelName.toLowerCase()] || 128000;
|
|
44
|
+
}
|
|
45
|
+
function formatMessagesForCompression(messages) {
|
|
46
|
+
return messages
|
|
47
|
+
.map((msg) => {
|
|
48
|
+
const role = msg.type;
|
|
49
|
+
let content = typeof msg.content === 'string'
|
|
50
|
+
? msg.content
|
|
51
|
+
: JSON.stringify(msg.content);
|
|
52
|
+
if (role === 'ai' && msg.tool_calls?.length) {
|
|
53
|
+
content += `\n[Tool Calls: ${JSON.stringify(msg.tool_calls)}]`;
|
|
54
|
+
}
|
|
55
|
+
return `[${role}] ${content}`;
|
|
56
|
+
})
|
|
57
|
+
.join('\n\n');
|
|
58
|
+
}
|
|
59
|
+
async function compressMessages(messages, existingSummary) {
|
|
60
|
+
if (messages.length === 0) {
|
|
61
|
+
return existingSummary || '';
|
|
62
|
+
}
|
|
63
|
+
const text = formatMessagesForCompression(messages);
|
|
64
|
+
const prompt = `请对以下对话内容进行结构化压缩摘要,要求如下:
|
|
65
|
+
|
|
66
|
+
1. 压缩比例至少 50%,去除重复、冗余、语气词和过渡性内容,但保留所有关键决策、结论、数据和待办事项。
|
|
67
|
+
2. 若对话包含多轮主题,请按主题分段压缩。
|
|
68
|
+
3. 无内容的项目可写“无”。
|
|
69
|
+
|
|
70
|
+
输出格式(Markdown):
|
|
71
|
+
|
|
72
|
+
## 时间
|
|
73
|
+
对话发生的时间范围或关键时间点。
|
|
74
|
+
|
|
75
|
+
## 摘要
|
|
76
|
+
概括本轮对话的核心内容。
|
|
77
|
+
|
|
78
|
+
## 决策
|
|
79
|
+
列出对话中做出的所有明确决策(如技术选型、方案确定、优先级调整等)。
|
|
80
|
+
|
|
81
|
+
## 结论
|
|
82
|
+
列出对话中达成的所有结论或共识。
|
|
83
|
+
|
|
84
|
+
## 待办
|
|
85
|
+
列出所有明确的待办事项(TODO),包括负责人(如有)。
|
|
86
|
+
|
|
87
|
+
## 遗留问题
|
|
88
|
+
列出尚未解决、需要后续跟进的问题。
|
|
89
|
+
|
|
90
|
+
## 原话摘要
|
|
91
|
+
摘录最具代表性的原话或关键信息,用引号标注。
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
对话内容如下:
|
|
96
|
+
|
|
97
|
+
${text}`;
|
|
98
|
+
const model = (0, model_1.createModel)({ streaming: false });
|
|
99
|
+
const response = await model.invoke([new messages_1.HumanMessage(prompt)]);
|
|
100
|
+
const newSummary = typeof response.content === 'string'
|
|
101
|
+
? response.content
|
|
102
|
+
: JSON.stringify(response.content);
|
|
103
|
+
if (existingSummary) {
|
|
104
|
+
return `${existingSummary}\n\n[后续对话摘要]\n${newSummary}`;
|
|
105
|
+
}
|
|
106
|
+
return newSummary;
|
|
107
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare const DB_PATH: string;
|
|
2
|
+
export interface SessionRow {
|
|
3
|
+
thread_id: string;
|
|
4
|
+
last_question: string;
|
|
5
|
+
last_ts: string;
|
|
6
|
+
}
|
|
7
|
+
export interface MemorySearchResult {
|
|
8
|
+
id: number;
|
|
9
|
+
type: string;
|
|
10
|
+
content: string;
|
|
11
|
+
keywords: string | null;
|
|
12
|
+
importance: number;
|
|
13
|
+
session_id: string | null;
|
|
14
|
+
created_at: string;
|
|
15
|
+
updated_at: string;
|
|
16
|
+
final_score: number;
|
|
17
|
+
}
|
|
18
|
+
export declare function searchMemories(query: string[], limit?: number): MemorySearchResult[];
|
|
19
|
+
export declare function threadIdExists(threadId: string): boolean;
|
|
20
|
+
export declare function initDb(): void;
|
|
21
|
+
export declare function listRecentSessions(): SessionRow[];
|
package/dist/agent/db.js
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.DB_PATH = void 0;
|
|
7
|
+
exports.searchMemories = searchMemories;
|
|
8
|
+
exports.threadIdExists = threadIdExists;
|
|
9
|
+
exports.initDb = initDb;
|
|
10
|
+
exports.listRecentSessions = listRecentSessions;
|
|
11
|
+
const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
|
|
12
|
+
const fs_1 = require("fs");
|
|
13
|
+
const path_1 = require("path");
|
|
14
|
+
const config_1 = require("./config");
|
|
15
|
+
const utils_1 = require("./utils");
|
|
16
|
+
exports.DB_PATH = (0, path_1.join)(config_1.WORKSPACE_DIR, '.data', 'checkpointer.db');
|
|
17
|
+
(0, fs_1.mkdirSync)((0, path_1.dirname)(exports.DB_PATH), { recursive: true });
|
|
18
|
+
function searchMemories(query, limit = 10) {
|
|
19
|
+
const trimmedQueries = query.map((q) => q.trim()).filter((q) => q.length > 0);
|
|
20
|
+
if (trimmedQueries.length === 0) {
|
|
21
|
+
return [];
|
|
22
|
+
}
|
|
23
|
+
const queryStr = trimmedQueries.join(' OR ').replace(/-/g, ' ');
|
|
24
|
+
const db = new better_sqlite3_1.default(exports.DB_PATH);
|
|
25
|
+
try {
|
|
26
|
+
const rows = db.prepare(`
|
|
27
|
+
WITH ranked AS (
|
|
28
|
+
SELECT
|
|
29
|
+
m.*,
|
|
30
|
+
-bm25(memory_fts, 10.0, 5.0) AS relevance_score,
|
|
31
|
+
(m.importance * 0.3) AS importance_score,
|
|
32
|
+
(
|
|
33
|
+
1.0 / (
|
|
34
|
+
1.0 +
|
|
35
|
+
((strftime('%s','now') - strftime('%s', m.updated_at)) / 86400.0)
|
|
36
|
+
)
|
|
37
|
+
) AS time_score
|
|
38
|
+
FROM memory_fts
|
|
39
|
+
JOIN memory m ON m.id = memory_fts.rowid
|
|
40
|
+
WHERE memory_fts MATCH ?
|
|
41
|
+
)
|
|
42
|
+
SELECT *,
|
|
43
|
+
(
|
|
44
|
+
relevance_score * 0.6 +
|
|
45
|
+
importance_score * 0.3 +
|
|
46
|
+
time_score * 0.1
|
|
47
|
+
) AS final_score
|
|
48
|
+
FROM ranked
|
|
49
|
+
ORDER BY final_score DESC
|
|
50
|
+
LIMIT ?
|
|
51
|
+
`).all(queryStr, limit);
|
|
52
|
+
return rows.map((r) => ({
|
|
53
|
+
id: r.id,
|
|
54
|
+
type: r.type,
|
|
55
|
+
content: r.content,
|
|
56
|
+
keywords: r.keywords,
|
|
57
|
+
importance: r.importance,
|
|
58
|
+
session_id: r.session_id,
|
|
59
|
+
created_at: r.created_at,
|
|
60
|
+
updated_at: r.updated_at,
|
|
61
|
+
final_score: r.final_score,
|
|
62
|
+
}));
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
db.close();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function threadIdExists(threadId) {
|
|
69
|
+
const db = new better_sqlite3_1.default(exports.DB_PATH);
|
|
70
|
+
try {
|
|
71
|
+
const row = db.prepare(`
|
|
72
|
+
SELECT 1 FROM checkpoints WHERE thread_id = ? LIMIT 1
|
|
73
|
+
`).get(threadId);
|
|
74
|
+
return !!row;
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
db.close();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function initDb() {
|
|
81
|
+
const db = new better_sqlite3_1.default(exports.DB_PATH);
|
|
82
|
+
try {
|
|
83
|
+
db.exec(`
|
|
84
|
+
CREATE TABLE IF NOT EXISTS memory (
|
|
85
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
86
|
+
type TEXT NOT NULL,
|
|
87
|
+
content TEXT NOT NULL,
|
|
88
|
+
keywords TEXT,
|
|
89
|
+
importance INTEGER DEFAULT 3,
|
|
90
|
+
session_id TEXT,
|
|
91
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
92
|
+
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
93
|
+
)
|
|
94
|
+
`);
|
|
95
|
+
db.exec(`
|
|
96
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS memory_fts USING fts5(
|
|
97
|
+
content,
|
|
98
|
+
keywords,
|
|
99
|
+
content='memory', content_rowid='id'
|
|
100
|
+
)
|
|
101
|
+
`);
|
|
102
|
+
db.exec(`
|
|
103
|
+
CREATE TRIGGER IF NOT EXISTS memory_fts_insert AFTER INSERT ON memory BEGIN
|
|
104
|
+
INSERT INTO memory_fts(rowid, content, keywords)
|
|
105
|
+
VALUES (new.id, new.content, new.keywords);
|
|
106
|
+
END;
|
|
107
|
+
|
|
108
|
+
CREATE TRIGGER IF NOT EXISTS memory_fts_delete AFTER DELETE ON memory BEGIN
|
|
109
|
+
INSERT INTO memory_fts(memory_fts, rowid, content, keywords)
|
|
110
|
+
VALUES ('delete', old.id, old.content, old.keywords);
|
|
111
|
+
END;
|
|
112
|
+
|
|
113
|
+
CREATE TRIGGER IF NOT EXISTS memory_fts_update AFTER UPDATE ON memory BEGIN
|
|
114
|
+
INSERT INTO memory_fts(memory_fts, rowid, content, keywords)
|
|
115
|
+
VALUES ('delete', old.id, old.content, old.keywords);
|
|
116
|
+
INSERT INTO memory_fts(rowid, content, keywords)
|
|
117
|
+
VALUES (new.id, new.content, new.keywords);
|
|
118
|
+
END;
|
|
119
|
+
`);
|
|
120
|
+
}
|
|
121
|
+
finally {
|
|
122
|
+
db.close();
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function listRecentSessions() {
|
|
126
|
+
const db = new better_sqlite3_1.default(exports.DB_PATH);
|
|
127
|
+
try {
|
|
128
|
+
const rows = db.prepare(`
|
|
129
|
+
WITH thread_last_ts AS (
|
|
130
|
+
SELECT
|
|
131
|
+
thread_id,
|
|
132
|
+
MAX(json_extract(CAST(checkpoint AS TEXT), '$.ts')) AS last_ts
|
|
133
|
+
FROM checkpoints
|
|
134
|
+
GROUP BY thread_id
|
|
135
|
+
)
|
|
136
|
+
SELECT
|
|
137
|
+
t.thread_id,
|
|
138
|
+
(SELECT json_extract(CAST(w.value AS TEXT), '$[0].kwargs.content')
|
|
139
|
+
FROM writes w
|
|
140
|
+
WHERE w.thread_id = t.thread_id
|
|
141
|
+
AND w.channel = 'messages'
|
|
142
|
+
AND json_extract(CAST(w.value AS TEXT), '$[0].id[2]') = 'HumanMessage'
|
|
143
|
+
ORDER BY w.checkpoint_id DESC
|
|
144
|
+
LIMIT 1) AS last_question,
|
|
145
|
+
t.last_ts
|
|
146
|
+
FROM thread_last_ts t
|
|
147
|
+
ORDER BY t.last_ts DESC
|
|
148
|
+
LIMIT 20
|
|
149
|
+
`).all();
|
|
150
|
+
return rows.map((r) => ({
|
|
151
|
+
thread_id: r.thread_id,
|
|
152
|
+
last_question: (0, utils_1.truncate)(r.last_question, 50),
|
|
153
|
+
last_ts: (0, utils_1.formatRelativeTime)(r.last_ts),
|
|
154
|
+
}));
|
|
155
|
+
}
|
|
156
|
+
finally {
|
|
157
|
+
db.close();
|
|
158
|
+
}
|
|
159
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { HookConfig, HooksConfig } from './config';
|
|
2
|
+
export type { HookConfig, HooksConfig };
|
|
3
|
+
export type HookResult = {
|
|
4
|
+
action: 'continue';
|
|
5
|
+
} | {
|
|
6
|
+
action: 'block';
|
|
7
|
+
reason: string;
|
|
8
|
+
} | {
|
|
9
|
+
action: 'inject';
|
|
10
|
+
message: string;
|
|
11
|
+
};
|
|
12
|
+
export declare function loadHooksConfig(): HooksConfig;
|
|
13
|
+
export declare function clearHooksCache(): void;
|
|
14
|
+
export declare function matchHooks(hooks: HookConfig[] | undefined, toolName: string): HookConfig[];
|
|
15
|
+
export declare function runHook(hook: HookConfig, env: Record<string, string>, timeout?: number): Promise<HookResult>;
|
|
16
|
+
export interface ToolHookContext {
|
|
17
|
+
toolName: string;
|
|
18
|
+
toolArgs: any;
|
|
19
|
+
toolCallId: string;
|
|
20
|
+
threadId: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function runPreToolUseHooks(context: ToolHookContext): Promise<HookResult>;
|
|
23
|
+
export interface PostToolHookContext extends ToolHookContext {
|
|
24
|
+
toolOutput: string;
|
|
25
|
+
}
|
|
26
|
+
export declare function runPostToolUseHooks(context: PostToolHookContext): Promise<HookResult>;
|
|
27
|
+
export declare function runSessionStartHooks(threadId: string): Promise<void>;
|