zhitalk 0.0.5 → 0.0.7

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.
Files changed (47) hide show
  1. package/README.md +2 -2
  2. package/dist/agent/agent.js +86 -63
  3. package/dist/agent/cli.js +39 -73
  4. package/dist/agent/colors.js +6 -44
  5. package/dist/agent/commands.js +22 -28
  6. package/dist/agent/config.js +20 -62
  7. package/dist/agent/context.js +14 -12
  8. package/dist/agent/db.js +17 -27
  9. package/dist/agent/hooks.d.ts +1 -1
  10. package/dist/agent/hooks.js +13 -22
  11. package/dist/agent/mcp/client.js +25 -29
  12. package/dist/agent/mcp/index.d.ts +1 -1
  13. package/dist/agent/mcp/index.js +8 -13
  14. package/dist/agent/mcp/wrapper.d.ts +2 -2
  15. package/dist/agent/mcp/wrapper.js +5 -8
  16. package/dist/agent/model.js +6 -10
  17. package/dist/agent/permission/exec.js +8 -11
  18. package/dist/agent/permission/is-dangerous-path.js +126 -18
  19. package/dist/agent/permission/is-safe-domains.js +1 -4
  20. package/dist/agent/permission/network.js +3 -6
  21. package/dist/agent/permission/read.js +3 -6
  22. package/dist/agent/permission/util.js +16 -26
  23. package/dist/agent/permission/write.js +5 -8
  24. package/dist/agent/prompt.js +9 -15
  25. package/dist/agent/skills.js +19 -24
  26. package/dist/agent/tools/agent_tool.js +2 -38
  27. package/dist/agent/tools/exec_tool.js +4 -7
  28. package/dist/agent/tools/load_skill_tool.js +3 -6
  29. package/dist/agent/tools/memory_create_tool.js +4 -10
  30. package/dist/agent/tools/memory_delete_tool.js +4 -10
  31. package/dist/agent/tools/memory_retrieve_tool.js +3 -6
  32. package/dist/agent/tools/profile_update_tool.js +11 -14
  33. package/dist/agent/tools/read_file_tool.js +4 -6
  34. package/dist/agent/tools/run_js_tool.js +3 -6
  35. package/dist/agent/tools/run_py_tool.js +4 -7
  36. package/dist/agent/tools/search.js +1 -4
  37. package/dist/agent/tools/web_fetch_tool.js +1 -4
  38. package/dist/agent/tools/web_search_tool.js +5 -8
  39. package/dist/agent/tools/write_file_tool.js +8 -9
  40. package/dist/agent/tools.js +76 -81
  41. package/dist/agent/utils.d.ts +1 -0
  42. package/dist/agent/utils.js +13 -6
  43. package/dist/index.js +23 -49
  44. package/dist/install.js +14 -50
  45. package/jest.config.js +11 -0
  46. package/package.json +8 -7
  47. package/dist/agent/permission/dangerous-path.json +0 -115
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # Zhitalk
1
+ # 智语 Zhitalk
2
2
 
3
- A personal AI Agent like OpenClaw, including tools, skills, memory, hook, sub-agent, MCP sever, etc. Run in the terminal.
3
+ [智语 Zhitalk](https://zhitalk.chat/) 是一个 AI Agent 个人助手,像 OpenClaw 小龙虾一样。 包含 tools skills memory hook subagent MCP-server Agent 功能。你可以和它聊天,给它分配任务,让它操作文件...
4
4
 
5
5
  ## Usage
6
6
 
@@ -1,41 +1,35 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.initAgent = initAgent;
4
- exports.runAgentStream = runAgentStream;
5
- exports.runSubAgent = runSubAgent;
6
- exports.compressContext = compressContext;
7
- const langgraph_checkpoint_sqlite_1 = require("@langchain/langgraph-checkpoint-sqlite");
8
- const messages_1 = require("@langchain/core/messages");
9
- const langgraph_1 = require("@langchain/langgraph");
10
- const langgraph_2 = require("@langchain/langgraph");
11
- const db_1 = require("./db");
12
- const tools_1 = require("./tools");
13
- const context_1 = require("./context");
14
- const prompt_1 = require("./prompt");
15
- const colors_1 = require("./colors");
16
- const read_1 = require("./permission/read");
17
- const write_1 = require("./permission/write");
18
- const exec_1 = require("./permission/exec");
19
- const network_1 = require("./permission/network");
20
- const hooks_1 = require("./hooks");
21
- const model_1 = require("./model");
1
+ import { SqliteSaver } from '@langchain/langgraph-checkpoint-sqlite';
2
+ import { SystemMessage, AIMessage, HumanMessage, ToolMessage, } from '@langchain/core/messages';
3
+ import { StateGraph, Annotation, START, END, interrupt, Command, } from '@langchain/langgraph';
4
+ import { messagesStateReducer } from '@langchain/langgraph';
5
+ import { DB_PATH } from './db.js';
6
+ import { tools, maybePersistedOutput, initTools } from './tools.js';
7
+ import { compressMessages } from './context.js';
8
+ import { systemPrompt } from './prompt.js';
9
+ import { formatToolLog } from './colors.js';
10
+ import { checkReadPermission } from './permission/read.js';
11
+ import { checkWritePermission } from './permission/write.js';
12
+ import { checkExecPermission } from './permission/exec.js';
13
+ import { checkNetworkPermission } from './permission/network.js';
14
+ import { runPreToolUseHooks, runPostToolUseHooks } from './hooks.js';
15
+ import { createModel } from './model.js';
22
16
  // ── 模型 ──────────────────────────────────────────────────
23
- const model = (0, model_1.createModel)({ streaming: true });
17
+ const model = createModel({ streaming: true });
24
18
  // ── State Schema ──────────────────────────────────────────
25
- const StateAnnotation = langgraph_1.Annotation.Root({
26
- messages: (0, langgraph_1.Annotation)({
27
- reducer: langgraph_2.messagesStateReducer,
19
+ const StateAnnotation = Annotation.Root({
20
+ messages: Annotation({
21
+ reducer: messagesStateReducer,
28
22
  default: () => [],
29
23
  }),
30
- contextSummary: (0, langgraph_1.Annotation)({
24
+ contextSummary: Annotation({
31
25
  reducer: (_prev, next) => next,
32
26
  default: () => null,
33
27
  }),
34
- compressionCount: (0, langgraph_1.Annotation)({
28
+ compressionCount: Annotation({
35
29
  reducer: (_prev, next) => next,
36
30
  default: () => 0,
37
31
  }),
38
- lastCompressedIndex: (0, langgraph_1.Annotation)({
32
+ lastCompressedIndex: Annotation({
39
33
  reducer: (_prev, next) => next,
40
34
  default: () => 0,
41
35
  }),
@@ -43,10 +37,10 @@ const StateAnnotation = langgraph_1.Annotation.Root({
43
37
  // ── Graph Nodes ───────────────────────────────────────────
44
38
  function shouldContinue(state) {
45
39
  const lastMessage = state.messages[state.messages.length - 1];
46
- if (messages_1.AIMessage.isInstance(lastMessage) && lastMessage.tool_calls?.length) {
40
+ if (AIMessage.isInstance(lastMessage) && lastMessage.tool_calls?.length) {
47
41
  return 'tools';
48
42
  }
49
- return langgraph_1.END;
43
+ return END;
50
44
  }
51
45
  function simplifyToolMessages(messages) {
52
46
  const toolIndices = [];
@@ -65,15 +59,41 @@ function simplifyToolMessages(messages) {
65
59
  const toolMsg = msg;
66
60
  if (toolMsg.name === 'read_file')
67
61
  return msg;
68
- return new messages_1.ToolMessage({
62
+ return new ToolMessage({
69
63
  content: `[Previous: used ${toolMsg.name}]`,
70
64
  tool_call_id: toolMsg.tool_call_id,
71
65
  name: toolMsg.name,
72
66
  });
73
67
  });
74
68
  }
69
+ /**
70
+ * 确保每个带有 tool_calls 的 AIMessage 后面都有对应的 ToolMessage。
71
+ * 当中断(如 ESC 取消)导致 tool 未执行时,消息历史会留下未完成的
72
+ * tool_calls,LLM API 会因此报错。此函数为缺失的 tool_calls 插入
73
+ * 占位 ToolMessage,使消息历史重新合法。
74
+ */
75
+ function ensureCompleteToolCalls(messages) {
76
+ const toolMessageIds = new Set(messages
77
+ .filter((msg) => msg.type === 'tool')
78
+ .map((msg) => msg.tool_call_id));
79
+ const result = [];
80
+ for (const msg of messages) {
81
+ result.push(msg);
82
+ if (AIMessage.isInstance(msg) && msg.tool_calls?.length) {
83
+ const missing = msg.tool_calls.filter((call) => call.id && !toolMessageIds.has(call.id));
84
+ for (const call of missing) {
85
+ result.push(new ToolMessage({
86
+ content: 'Tool execution was interrupted or failed to complete.',
87
+ tool_call_id: call.id ?? '',
88
+ name: call.name ?? '',
89
+ }));
90
+ }
91
+ }
92
+ }
93
+ return result;
94
+ }
75
95
  // ── 记忆 ──────────────────────────────────────────────────
76
- const checkpointer = langgraph_checkpoint_sqlite_1.SqliteSaver.fromConnString(db_1.DB_PATH);
96
+ const checkpointer = SqliteSaver.fromConnString(DB_PATH);
77
97
  // ── Agent Graph 工厂 ──────────────────────────────────────
78
98
  function createAgentGraph(toolList) {
79
99
  const modelWithTheseTools = model.bindTools(toolList);
@@ -81,7 +101,7 @@ function createAgentGraph(toolList) {
81
101
  let modelMessages = state.messages ?? [];
82
102
  // compact context
83
103
  if (state.contextSummary && state.lastCompressedIndex > 0) {
84
- const summaryMsg = new messages_1.SystemMessage(`历史对话摘要:\n\n${state.contextSummary}`);
104
+ const summaryMsg = new SystemMessage(`历史对话摘要:\n\n${state.contextSummary}`);
85
105
  modelMessages = [
86
106
  summaryMsg,
87
107
  ...modelMessages.slice(state.lastCompressedIndex),
@@ -91,7 +111,9 @@ function createAgentGraph(toolList) {
91
111
  modelMessages = simplifyToolMessages(modelMessages);
92
112
  // keep recent 300 items
93
113
  modelMessages = modelMessages.slice(0, 300);
94
- const messages = [new messages_1.SystemMessage(prompt_1.systemPrompt), ...modelMessages];
114
+ // 修复因中断/截断导致的未完成 tool_calls
115
+ modelMessages = ensureCompleteToolCalls(modelMessages);
116
+ const messages = [new SystemMessage(systemPrompt), ...modelMessages];
95
117
  const response = await modelWithTheseTools.invoke(messages, config);
96
118
  return { messages: [response] };
97
119
  }
@@ -102,12 +124,12 @@ function createAgentGraph(toolList) {
102
124
  .map((msg) => msg.tool_call_id));
103
125
  let aiMessage;
104
126
  for (let i = messages.length - 1; i >= 0; i--) {
105
- if (messages_1.AIMessage.isInstance(messages[i])) {
127
+ if (AIMessage.isInstance(messages[i])) {
106
128
  aiMessage = messages[i];
107
129
  break;
108
130
  }
109
131
  }
110
- if (!aiMessage || !messages_1.AIMessage.isInstance(aiMessage)) {
132
+ if (!aiMessage || !AIMessage.isInstance(aiMessage)) {
111
133
  throw new Error('ToolNode only accepts AIMessages as input.');
112
134
  }
113
135
  const toolCalls = aiMessage.tool_calls?.filter((call) => call.id == null || !toolMessageIds.has(call.id)) ?? [];
@@ -122,16 +144,16 @@ function createAgentGraph(toolList) {
122
144
  const level = tool?.permission_level;
123
145
  let decision;
124
146
  if (level === 'read') {
125
- decision = (0, read_1.checkReadPermission)(call);
147
+ decision = checkReadPermission(call);
126
148
  }
127
149
  else if (level === 'write') {
128
- decision = (0, write_1.checkWritePermission)(call);
150
+ decision = checkWritePermission(call);
129
151
  }
130
152
  else if (level === 'exec') {
131
- decision = (0, exec_1.checkExecPermission)(call);
153
+ decision = checkExecPermission(call);
132
154
  }
133
155
  else if (level === 'network') {
134
- decision = (0, network_1.checkNetworkPermission)(call);
156
+ decision = checkNetworkPermission(call);
135
157
  }
136
158
  else if (level === 'mcp') {
137
159
  decision = { action: 'confirm' };
@@ -143,7 +165,7 @@ function createAgentGraph(toolList) {
143
165
  allowCalls.push(call);
144
166
  }
145
167
  else if (decision.action === 'block') {
146
- blockMessages.push(new messages_1.ToolMessage({
168
+ blockMessages.push(new ToolMessage({
147
169
  content: decision.reason,
148
170
  tool_call_id: call.id ?? '',
149
171
  name: call.name,
@@ -156,18 +178,18 @@ function createAgentGraph(toolList) {
156
178
  async function executeCalls(calls) {
157
179
  return Promise.all(calls.map(async (call) => {
158
180
  const tool = toolList.find((t) => t.name === call.name);
159
- console.log((0, colors_1.formatToolLog)(call.name, JSON.stringify(call.args)));
181
+ console.log(formatToolLog(call.name, JSON.stringify(call.args)));
160
182
  try {
161
183
  const threadId = config?.configurable?.thread_id || '';
162
184
  // PreToolUse hook
163
- const preResult = await (0, hooks_1.runPreToolUseHooks)({
185
+ const preResult = await runPreToolUseHooks({
164
186
  toolName: call.name,
165
187
  toolArgs: call.args,
166
188
  toolCallId: call.id ?? '',
167
189
  threadId,
168
190
  });
169
191
  if (preResult.action === 'block') {
170
- return new messages_1.ToolMessage({
192
+ return new ToolMessage({
171
193
  content: preResult.reason,
172
194
  tool_call_id: call.id ?? '',
173
195
  name: call.name,
@@ -178,7 +200,7 @@ function createAgentGraph(toolList) {
178
200
  const output = await tool.invoke({ ...call, type: 'tool_call' }, config);
179
201
  let content = typeof output === 'string' ? output : JSON.stringify(output);
180
202
  // PostToolUse hook
181
- const postResult = await (0, hooks_1.runPostToolUseHooks)({
203
+ const postResult = await runPostToolUseHooks({
182
204
  toolName: call.name,
183
205
  toolArgs: call.args,
184
206
  toolOutput: content,
@@ -194,15 +216,15 @@ function createAgentGraph(toolList) {
194
216
  if (preResult.action === 'inject') {
195
217
  content = `[Hook injection]\n${preResult.message}\n\n${content}`;
196
218
  }
197
- const finalContent = await (0, tools_1.maybePersistedOutput)(content, call.id ?? '');
198
- return new messages_1.ToolMessage({
219
+ const finalContent = await maybePersistedOutput(content, call.id ?? '');
220
+ return new ToolMessage({
199
221
  content: finalContent,
200
222
  tool_call_id: call.id ?? '',
201
223
  name: call.name,
202
224
  });
203
225
  }
204
226
  catch (e) {
205
- return new messages_1.ToolMessage({
227
+ return new ToolMessage({
206
228
  content: `Error: ${e.message}\n Please fix your mistakes.`,
207
229
  tool_call_id: call.id ?? '',
208
230
  name: call.name,
@@ -214,9 +236,9 @@ function createAgentGraph(toolList) {
214
236
  if (confirmCalls.length === 0) {
215
237
  return { messages: [...allowOutputs, ...blockMessages] };
216
238
  }
217
- const result = (0, langgraph_1.interrupt)({ toolCalls: confirmCalls });
239
+ const result = interrupt({ toolCalls: confirmCalls });
218
240
  if (result !== 'approved') {
219
- const deniedMessages = confirmCalls.map((call) => new messages_1.ToolMessage({
241
+ const deniedMessages = confirmCalls.map((call) => new ToolMessage({
220
242
  content: 'Tool execution was denied by the user.',
221
243
  tool_call_id: call.id ?? '',
222
244
  name: call.name,
@@ -228,13 +250,13 @@ function createAgentGraph(toolList) {
228
250
  const confirmOutputs = await executeCalls(confirmCalls);
229
251
  return { messages: [...allowOutputs, ...blockMessages, ...confirmOutputs] };
230
252
  }
231
- const workflow = new langgraph_1.StateGraph(StateAnnotation)
253
+ const workflow = new StateGraph(StateAnnotation)
232
254
  .addNode('model_request', modelRequest)
233
255
  .addNode('tools', toolNode)
234
- .addEdge(langgraph_1.START, 'model_request')
256
+ .addEdge(START, 'model_request')
235
257
  .addConditionalEdges('model_request', shouldContinue, {
236
258
  tools: 'tools',
237
- [langgraph_1.END]: langgraph_1.END,
259
+ [END]: END,
238
260
  })
239
261
  .addEdge('tools', 'model_request');
240
262
  return workflow.compile({
@@ -244,10 +266,10 @@ function createAgentGraph(toolList) {
244
266
  // ── Agent 创建 ────────────────────────────────────────────
245
267
  let agent = null;
246
268
  let subAgent = null;
247
- async function initAgent() {
248
- await (0, tools_1.initTools)();
249
- agent = createAgentGraph(tools_1.tools);
250
- subAgent = createAgentGraph(tools_1.tools.filter((t) => t.name !== 'agent_tool'));
269
+ export async function initAgent() {
270
+ await initTools();
271
+ agent = createAgentGraph(tools);
272
+ subAgent = createAgentGraph(tools.filter((t) => t.name !== 'agent_tool'));
251
273
  }
252
274
  function getAgent() {
253
275
  if (!agent)
@@ -264,12 +286,13 @@ async function _runAgent(compiledAgent, userMessage, onToken, onToolConfirmation
264
286
  const config = { configurable: { thread_id: threadId } };
265
287
  let fullResponse = '';
266
288
  let usageMetadata;
267
- let input = { messages: [new messages_1.HumanMessage(userMessage)] };
289
+ let input = { messages: [new HumanMessage(userMessage)] };
268
290
  while (true) {
269
291
  const stream = await compiledAgent.stream(input, {
270
292
  ...config,
271
293
  streamMode: 'messages',
272
294
  signal,
295
+ recursionLimit: 50,
273
296
  });
274
297
  for await (const chunk of stream) {
275
298
  if (signal?.aborted) {
@@ -296,7 +319,7 @@ async function _runAgent(compiledAgent, userMessage, onToken, onToolConfirmation
296
319
  if (!interruptedTask)
297
320
  break;
298
321
  const confirmed = await onToolConfirmation(interruptedTask.interrupts[0].value.toolCalls);
299
- input = new langgraph_1.Command({ resume: confirmed ? 'approved' : 'denied' });
322
+ input = new Command({ resume: confirmed ? 'approved' : 'denied' });
300
323
  }
301
324
  return { response: fullResponse, usageMetadata };
302
325
  }
@@ -308,7 +331,7 @@ async function _runAgent(compiledAgent, userMessage, onToken, onToolConfirmation
308
331
  * @param {string} threadId - 会话 ID,相同 ID 自动续上历史记录
309
332
  * @returns {Promise<{ response: string; usageMetadata?: UsageMetadata }>} 完整的 AI 回复文本及 token 使用信息
310
333
  */
311
- async function runAgentStream(userMessage, onToken, onToolConfirmation, threadId = 'default-session', signal) {
334
+ export async function runAgentStream(userMessage, onToken, onToolConfirmation, threadId = 'default-session', signal) {
312
335
  return _runAgent(getAgent(), userMessage, onToken, onToolConfirmation, threadId, signal);
313
336
  }
314
337
  /**
@@ -316,14 +339,14 @@ async function runAgentStream(userMessage, onToken, onToolConfirmation, threadId
316
339
  * @param {string} prompt - 给 subagent 的任务提示
317
340
  * @returns {Promise<string>} subagent 的最终回复
318
341
  */
319
- async function runSubAgent(prompt) {
342
+ export async function runSubAgent(prompt) {
320
343
  const threadId = `subagent-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
321
344
  const result = await _runAgent(getSubAgent(), prompt.trim(), () => { }, // 不需要流式输出
322
345
  async () => true, // subagent 自动确认 tools
323
346
  threadId, undefined);
324
347
  return result.response;
325
348
  }
326
- async function compressContext(threadId) {
349
+ export async function compressContext(threadId) {
327
350
  const config = { configurable: { thread_id: threadId } };
328
351
  const currentState = await getAgent().getState(config);
329
352
  const messages = currentState.values.messages || [];
@@ -335,7 +358,7 @@ async function compressContext(threadId) {
335
358
  return { didCompress: false, count };
336
359
  }
337
360
  const toCompress = messages.slice(lastIndex, messages.length - recentKeep);
338
- const newSummary = await (0, context_1.compressMessages)(toCompress, existingSummary);
361
+ const newSummary = await compressMessages(toCompress, existingSummary);
339
362
  await getAgent().updateState(config, {
340
363
  contextSummary: newSummary,
341
364
  lastCompressedIndex: messages.length - recentKeep,
package/dist/agent/cli.js CHANGED
@@ -1,48 +1,14 @@
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.interactiveChat = interactiveChat;
37
- const readline = __importStar(require("readline"));
38
- const fs_1 = require("fs");
39
- const path_1 = require("path");
40
- const agent_1 = require("./agent");
41
- const context_1 = require("./context");
42
- const colors_1 = require("./colors");
43
- const commands_1 = require("./commands");
44
- const hooks_1 = require("./hooks");
45
- const pkg = JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(__dirname, '../../package.json'), 'utf-8'));
1
+ import * as readline from 'readline';
2
+ import { readFileSync } from 'fs';
3
+ import { join, dirname } from 'path';
4
+ import { fileURLToPath } from 'url';
5
+ import { runAgentStream, compressContext } from './agent.js';
6
+ import { getModelContextLimit } from './context.js';
7
+ import { color, formatToolLog } from './colors.js';
8
+ import { threadId, commands } from './commands.js';
9
+ import { runSessionStartHooks } from './hooks.js';
10
+ const __dirname = dirname(fileURLToPath(import.meta.url));
11
+ const pkg = JSON.parse(readFileSync(join(__dirname, '../../package.json'), 'utf-8'));
46
12
  function createInterface() {
47
13
  return readline.createInterface({
48
14
  input: process.stdin,
@@ -50,14 +16,14 @@ function createInterface() {
50
16
  });
51
17
  }
52
18
  async function printBanner() {
53
- const figlet = (await Promise.resolve().then(() => __importStar(require('figlet')))).default;
54
- const { default: boxen } = await Promise.resolve().then(() => __importStar(require('boxen')));
55
- console.log(colors_1.color.banner(figlet.textSync(pkg.name, { font: 'Slant' })));
19
+ const figlet = (await import('figlet')).default;
20
+ const { default: boxen } = await import('boxen');
21
+ console.log(color.banner(figlet.textSync(pkg.name, { font: 'Slant' })));
56
22
  const info = [
57
- `${colors_1.color.gray('Description')}: ${pkg.description}`,
58
- `${colors_1.color.gray('Version')}: ${pkg.version}`,
59
- `${colors_1.color.gray('Author')}: ${pkg.author}`,
60
- `${colors_1.color.gray('Docs')}: ${pkg.docs}`,
23
+ `${color.gray('Description')}: ${pkg.description}`,
24
+ `${color.gray('Version')}: ${pkg.version}`,
25
+ `${color.gray('Author')}: ${pkg.author}`,
26
+ `${color.gray('Docs')}: ${pkg.docs}`,
61
27
  ].join('\n');
62
28
  console.log(boxen(info, {
63
29
  padding: 1,
@@ -67,7 +33,7 @@ async function printBanner() {
67
33
  console.log('Usage:');
68
34
  console.log(' ESC - Cancel AI request');
69
35
  console.log(' exit - Exit the chat');
70
- for (const [name, cmd] of commands_1.commands) {
36
+ for (const [name, cmd] of commands) {
71
37
  console.log(` /${name.padEnd(8)} - ${cmd.description}`);
72
38
  }
73
39
  console.log();
@@ -83,12 +49,12 @@ function prompt(question) {
83
49
  }
84
50
  async function chat(userInput) {
85
51
  const rl = createInterface();
86
- process.stdout.write('\n' + colors_1.color.aiPrefix());
52
+ process.stdout.write('\n' + color.aiPrefix());
87
53
  const controller = new AbortController();
88
54
  // 监听 ESC 键,中断 AI 请求
89
55
  const escListener = (_str, key) => {
90
56
  if (key.name === 'escape' || key.name === 'esc') {
91
- process.stdout.write('\n\n' + colors_1.color.cancelled('[Cancelled]') + '\n');
57
+ process.stdout.write('\n\n' + color.cancelled('[Cancelled]') + '\n');
92
58
  controller.abort();
93
59
  rl.close();
94
60
  }
@@ -97,18 +63,18 @@ async function chat(userInput) {
97
63
  process.stdin.on('keypress', escListener);
98
64
  let usageMetadata;
99
65
  try {
100
- const result = await (0, agent_1.runAgentStream)(userInput, (token) => {
66
+ const result = await runAgentStream(userInput, (token) => {
101
67
  process.stdout.write(token);
102
68
  }, async (toolCalls) => {
103
69
  for (const call of toolCalls) {
104
- console.log((0, colors_1.formatToolLog)(call.name, JSON.stringify(call.args)));
70
+ console.log(formatToolLog(call.name, JSON.stringify(call.args)));
105
71
  }
106
72
  const answer = await new Promise((resolve) => {
107
73
  rl.question('确认执行以上工具? (y/n): ', resolve);
108
74
  });
109
75
  return (answer.trim().toLowerCase() === 'y' ||
110
76
  answer.trim().toLowerCase() === 'yes');
111
- }, commands_1.threadId, controller.signal);
77
+ }, threadId, controller.signal);
112
78
  usageMetadata = result.usageMetadata;
113
79
  }
114
80
  catch (err) {
@@ -121,23 +87,23 @@ async function chat(userInput) {
121
87
  rl.close();
122
88
  }
123
89
  if (usageMetadata) {
124
- const limit = (0, context_1.getModelContextLimit)();
90
+ const limit = getModelContextLimit();
125
91
  const percentage = (usageMetadata.total_tokens / limit) * 100;
126
92
  const percentageStr = percentage.toFixed(1);
127
93
  const tokenText = `Tokens: ${usageMetadata.total_tokens.toLocaleString()} / ${limit.toLocaleString()} (${percentageStr}%)`;
128
94
  if (percentage >= 80) {
129
95
  process.stdout.write('\n' +
130
- colors_1.color.error(tokenText) +
96
+ color.error(tokenText) +
131
97
  '\n' +
132
- colors_1.color.error('警告:Context window 接近大模型接口上限,即将压缩 Context,可能会丢失信息') +
98
+ color.error('警告:Context window 接近大模型接口上限,即将压缩 Context,可能会丢失信息') +
133
99
  '\n' +
134
- colors_1.color.error('建议输入 /new 命令开启新会话'));
100
+ color.error('建议输入 /new 命令开启新会话'));
135
101
  try {
136
- const result = await (0, agent_1.compressContext)(commands_1.threadId);
102
+ const result = await compressContext(threadId);
137
103
  if (result.didCompress) {
138
- process.stdout.write('\n' + colors_1.color.error(`Context 已压缩(第 ${result.count} 次),已保留最近 6 条消息`) + '\n');
104
+ process.stdout.write('\n' + color.error(`Context 已压缩(第 ${result.count} 次),已保留最近 6 条消息`) + '\n');
139
105
  if (result.count >= 3) {
140
- process.stdout.write(colors_1.color.error('强烈建议输入 /new 命令开启新会话,以避免信息丢失') + '\n');
106
+ process.stdout.write(color.error('强烈建议输入 /new 命令开启新会话,以避免信息丢失') + '\n');
141
107
  }
142
108
  }
143
109
  }
@@ -146,32 +112,32 @@ async function chat(userInput) {
146
112
  }
147
113
  }
148
114
  else {
149
- process.stdout.write('\n' + colors_1.color.tokenInfo(tokenText));
115
+ process.stdout.write('\n' + color.tokenInfo(tokenText));
150
116
  }
151
117
  }
152
118
  process.stdout.write('\n\n');
153
119
  }
154
- async function interactiveChat() {
120
+ export async function interactiveChat() {
155
121
  await printBanner();
156
- await (0, hooks_1.runSessionStartHooks)(commands_1.threadId);
122
+ await runSessionStartHooks(threadId);
157
123
  while (true) {
158
- const userInput = await prompt(colors_1.color.userPrefix());
124
+ const userInput = await prompt(color.userPrefix());
159
125
  if (!userInput.trim())
160
126
  continue;
161
127
  if (userInput.toLowerCase() === 'exit') {
162
- console.log(colors_1.color.goodbye('再见!'));
128
+ console.log('Bye Bye~ Have a nice day~\n');
163
129
  break;
164
130
  }
165
131
  if (userInput.startsWith('/')) {
166
132
  const parts = userInput.trim().split(/\s+/);
167
133
  const cmdName = parts[0].slice(1);
168
134
  const args = parts.slice(1);
169
- const cmd = commands_1.commands.get(cmdName);
135
+ const cmd = commands.get(cmdName);
170
136
  if (cmd) {
171
137
  await cmd.execute(args);
172
138
  }
173
139
  else {
174
- console.log(colors_1.color.error(`Unknown command: ${cmdName}`));
140
+ console.log(color.error(`Unknown command: ${cmdName}`));
175
141
  }
176
142
  continue;
177
143
  }
@@ -179,7 +145,7 @@ async function interactiveChat() {
179
145
  await chat(userInput);
180
146
  }
181
147
  catch (err) {
182
- console.error(colors_1.color.error(`请求出错: ${err.message}`));
148
+ console.error(color.error(`请求出错: ${err.message}`));
183
149
  }
184
150
  }
185
151
  }
@@ -1,44 +1,6 @@
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
1
  let _chalk = null;
40
- async function initColors() {
41
- const mod = (await Promise.resolve().then(() => __importStar(require('chalk'))));
2
+ export async function initColors() {
3
+ const mod = (await import('chalk'));
42
4
  _chalk = mod.default;
43
5
  }
44
6
  function createPlainFallback() {
@@ -55,7 +17,7 @@ function ck() {
55
17
  }
56
18
  return _chalk;
57
19
  }
58
- exports.color = {
20
+ export const color = {
59
21
  banner: (text) => ck().cyanBright.bold(text),
60
22
  userPrefix: () => ck().greenBright.bold('You: '),
61
23
  aiPrefix: () => ck().cyanBright.bold('AI: '),
@@ -72,10 +34,10 @@ exports.color = {
72
34
  info: (text) => ck().blueBright(text),
73
35
  good: (text) => ck().greenBright(text),
74
36
  };
75
- function formatToolLog(name, detail) {
76
- const parts = [exports.color.toolTag(), exports.color.toolName(name), exports.color.toolAction()];
37
+ export function formatToolLog(name, detail) {
38
+ const parts = [color.toolTag(), color.toolName(name), color.toolAction()];
77
39
  if (detail) {
78
- parts.push(exports.color.toolArg(detail));
40
+ parts.push(color.toolArg(detail));
79
41
  }
80
42
  return '\n' + parts.join(' ');
81
43
  }