@zhin.js/agent 0.0.16 → 0.0.18

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 (69) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/lib/builtin-tools.d.ts +7 -50
  3. package/lib/builtin-tools.d.ts.map +1 -1
  4. package/lib/builtin-tools.js +13 -377
  5. package/lib/builtin-tools.js.map +1 -1
  6. package/lib/discover-agents.d.ts +28 -0
  7. package/lib/discover-agents.d.ts.map +1 -0
  8. package/lib/discover-agents.js +116 -0
  9. package/lib/discover-agents.js.map +1 -0
  10. package/lib/discover-skills.d.ts +49 -0
  11. package/lib/discover-skills.d.ts.map +1 -0
  12. package/lib/discover-skills.js +297 -0
  13. package/lib/discover-skills.js.map +1 -0
  14. package/lib/discover-tools.d.ts +56 -0
  15. package/lib/discover-tools.d.ts.map +1 -0
  16. package/lib/discover-tools.js +263 -0
  17. package/lib/discover-tools.js.map +1 -0
  18. package/lib/discovery-utils.d.ts +27 -0
  19. package/lib/discovery-utils.d.ts.map +1 -0
  20. package/lib/discovery-utils.js +96 -0
  21. package/lib/discovery-utils.js.map +1 -0
  22. package/lib/init/create-zhin-agent.d.ts.map +1 -1
  23. package/lib/init/create-zhin-agent.js +2 -1
  24. package/lib/init/create-zhin-agent.js.map +1 -1
  25. package/lib/init/register-builtin-tools.d.ts.map +1 -1
  26. package/lib/init/register-builtin-tools.js +170 -38
  27. package/lib/init/register-builtin-tools.js.map +1 -1
  28. package/lib/init/register-db-models.js +3 -3
  29. package/lib/init/register-db-models.js.map +1 -1
  30. package/lib/init/register-db-upgrade.js +2 -2
  31. package/lib/init/register-db-upgrade.js.map +1 -1
  32. package/lib/init/register-management-tools.js +1 -1
  33. package/lib/init/register-management-tools.js.map +1 -1
  34. package/lib/service.d.ts +4 -8
  35. package/lib/service.d.ts.map +1 -1
  36. package/lib/service.js +23 -112
  37. package/lib/service.js.map +1 -1
  38. package/lib/subagent.js +1 -1
  39. package/lib/subagent.js.map +1 -1
  40. package/lib/zhin-agent/builtin-tools.d.ts +1 -1
  41. package/lib/zhin-agent/builtin-tools.d.ts.map +1 -1
  42. package/lib/zhin-agent/config.d.ts +8 -1
  43. package/lib/zhin-agent/config.d.ts.map +1 -1
  44. package/lib/zhin-agent/config.js +8 -1
  45. package/lib/zhin-agent/config.js.map +1 -1
  46. package/lib/zhin-agent/index.d.ts +3 -3
  47. package/lib/zhin-agent/index.d.ts.map +1 -1
  48. package/lib/zhin-agent/index.js +52 -29
  49. package/lib/zhin-agent/index.js.map +1 -1
  50. package/lib/zhin-agent/tool-collector.js +1 -1
  51. package/package.json +3 -3
  52. package/src/builtin-tools.ts +21 -404
  53. package/src/discover-agents.ts +138 -0
  54. package/src/discover-skills.ts +325 -0
  55. package/src/discover-tools.ts +302 -0
  56. package/src/discovery-utils.ts +96 -0
  57. package/src/init/create-zhin-agent.ts +2 -1
  58. package/src/init/register-ai-trigger.ts +1 -1
  59. package/src/init/register-builtin-tools.ts +167 -46
  60. package/src/init/register-db-models.ts +3 -3
  61. package/src/init/register-db-upgrade.ts +2 -2
  62. package/src/init/register-management-tools.ts +1 -1
  63. package/src/init/register-message-recorder.ts +1 -1
  64. package/src/service.ts +28 -132
  65. package/src/subagent.ts +1 -1
  66. package/src/zhin-agent/builtin-tools.ts +1 -1
  67. package/src/zhin-agent/config.ts +10 -2
  68. package/src/zhin-agent/index.ts +51 -29
  69. package/src/zhin-agent/tool-collector.ts +1 -1
@@ -7,7 +7,7 @@
7
7
 
8
8
  import type { ToolContext } from '@zhin.js/core';
9
9
  import type { AgentTool } from '@zhin.js/core';
10
- import type { ConversationMemory } from '../conversation-memory.js';
10
+ import type { ConversationMemory } from '@zhin.js/ai';
11
11
  import type { UserProfileStore } from '../user-profile.js';
12
12
  import type { FollowUpManager } from '../follow-up.js';
13
13
  import type { SubagentManager, SubagentOrigin } from '../subagent.js';
@@ -2,8 +2,8 @@
2
2
  * ZhinAgent 配置、常量、类型定义
3
3
  */
4
4
 
5
- import type { RateLimitConfig } from '../rate-limiter.js';
6
- import { DEFAULT_CONTEXT_TOKENS } from '../compaction.js';
5
+ import type { RateLimitConfig } from '@zhin.js/ai';
6
+ import { DEFAULT_CONTEXT_TOKENS } from '@zhin.js/ai';
7
7
 
8
8
  export type ModelSizeHint = 'small' | 'medium' | 'large';
9
9
 
@@ -56,6 +56,14 @@ export const PERM_MAP: Record<string, number> = {
56
56
 
57
57
  export type OnChunkCallback = (chunk: string, full: string) => void;
58
58
 
59
+ /** 上下文感知内置工具的关键词触发正则 */
60
+ export const KEYWORD_TRIGGERS = {
61
+ chatHistory: /之前|上次|历史|回忆|聊过|记录|还记得|曾经/i,
62
+ userProfile: /偏好|设置|配置|档案|资料|时区|timezone|profile|喜好|我叫|叫我|记住我/i,
63
+ scheduleFollowUp: /提醒|定时|过一会|跟进|别忘|取消提醒|reminder|分钟后|小时后/i,
64
+ spawnTask: /后台|子任务|spawn|异步|background|并行|独立处理/i,
65
+ } as const;
66
+
59
67
  export interface ZhinAgentConfig {
60
68
  persona?: string;
61
69
  maxIterations?: number;
@@ -18,21 +18,21 @@
18
18
 
19
19
  import { Logger } from '@zhin.js/core';
20
20
  import type { Tool, ToolContext, SkillFeature, AIProvider, AgentTool, ChatMessage, ContentPart } from '@zhin.js/core';
21
- import { createAgent } from '../agent.js';
22
- import { SessionManager, createMemorySessionManager } from '../session.js';
23
- import type { ContextManager } from '../context-manager.js';
24
- import { ConversationMemory } from '../conversation-memory.js';
25
- import type { OutputElement } from '../output.js';
26
- import { parseOutput } from '../output.js';
21
+ import { createAgent } from '@zhin.js/ai';
22
+ import { SessionManager, createMemorySessionManager } from '@zhin.js/ai';
23
+ import type { ContextManager } from '@zhin.js/ai';
24
+ import { ConversationMemory } from '@zhin.js/ai';
25
+ import type { OutputElement } from '@zhin.js/ai';
26
+ import { parseOutput } from '@zhin.js/ai';
27
27
  import { UserProfileStore } from '../user-profile.js';
28
- import { RateLimiter } from '../rate-limiter.js';
29
- import { detectTone } from '../tone-detector.js';
28
+ import { RateLimiter } from '@zhin.js/ai';
29
+ import { detectTone } from '@zhin.js/ai';
30
30
  import { FollowUpManager, type FollowUpSender } from '../follow-up.js';
31
31
  import { SubagentManager, type SubagentResultSender } from '../subagent.js';
32
32
  import {
33
33
  pruneHistoryForContext,
34
34
  DEFAULT_CONTEXT_TOKENS,
35
- } from '../compaction.js';
35
+ } from '@zhin.js/ai';
36
36
  import { triggerAIHook, createAIHookEvent } from '../hooks.js';
37
37
 
38
38
  // ── Sub-modules ─────────────────────────────────────────────────────
@@ -40,6 +40,7 @@ import {
40
40
  type ZhinAgentConfig,
41
41
  type OnChunkCallback,
42
42
  DEFAULT_CONFIG,
43
+ KEYWORD_TRIGGERS,
43
44
  } from './config.js';
44
45
  import { applyExecPolicyToTools } from './exec-policy.js';
45
46
  import { collectRelevantTools } from './tool-collector.js';
@@ -62,6 +63,11 @@ export type { ZhinAgentConfig, OnChunkCallback } from './config.js';
62
63
  const logger = new Logger(null, 'ZhinAgent');
63
64
  const now = () => performance.now();
64
65
 
66
+ /** Strip `<think>…</think>` blocks that some reasoning models embed in content. */
67
+ function stripThinkBlocks(text: string): string {
68
+ return text.replace(/<think>[\s\S]*?<\/think>\s*/g, '').trim();
69
+ }
70
+
65
71
  // ============================================================================
66
72
  // ZhinAgent
67
73
  // ============================================================================
@@ -212,16 +218,16 @@ export class ZhinAgent {
212
218
  });
213
219
 
214
220
  // Inject context-aware built-in tools on keyword match
215
- if (/之前|上次|历史|回忆|聊过|记录|还记得|曾经/i.test(content)) {
221
+ if (KEYWORD_TRIGGERS.chatHistory.test(content)) {
216
222
  allTools.push(createChatHistoryTool(sessionId, this.memory));
217
223
  }
218
- if (/偏好|设置|配置|档案|资料|时区|timezone|profile|喜好|我叫|叫我|记住我/i.test(content)) {
224
+ if (KEYWORD_TRIGGERS.userProfile.test(content)) {
219
225
  allTools.push(createUserProfileTool(userId, this.userProfiles));
220
226
  }
221
- if (/提醒|定时|过一会|跟进|别忘|取消提醒|reminder|分钟后|小时后/i.test(content)) {
227
+ if (KEYWORD_TRIGGERS.scheduleFollowUp.test(content)) {
222
228
  allTools.push(createScheduleFollowUpTool(sessionId, context, this.followUps));
223
229
  }
224
- if (this.subagentManager && /后台|子任务|spawn|异步|background|并行|独立处理/i.test(content)) {
230
+ if (this.subagentManager && KEYWORD_TRIGGERS.spawnTask.test(content)) {
225
231
  allTools.push(createSpawnTaskTool(context, this.subagentManager));
226
232
  }
227
233
 
@@ -352,7 +358,7 @@ ${preData ? `\nPre-fetched data:\n${preData}\n` : ''}`;
352
358
 
353
359
  const userMessageWithHistory = buildUserMessageWithHistory(historyMessages, content);
354
360
  const result = await agent.run(userMessageWithHistory, []);
355
- reply = result.content || this.fallbackFormat(result.toolCalls);
361
+ reply = stripThinkBlocks(result.content) || this.fallbackFormat(result.toolCalls);
356
362
  logger.info(`[Agent 路径] 过滤=${filterMs}ms, 记忆=${memMs}ms, Agent=${(now() - tAgent).toFixed(0)}ms, 总=${(now() - t0).toFixed(0)}ms`);
357
363
  }
358
364
 
@@ -433,16 +439,25 @@ ${preData ? `\nPre-fetched data:\n${preData}\n` : ''}`;
433
439
  let reply = '';
434
440
  try {
435
441
  for await (const chunk of this.provider.chatStream({ model: visionModel, messages })) {
436
- const delta = chunk.choices?.[0]?.delta?.content;
437
- if (delta && typeof delta === 'string') {
438
- reply += delta;
439
- if (onChunk) onChunk(delta, reply);
442
+ const delta = chunk.choices?.[0]?.delta;
443
+ if (!delta) continue;
444
+ const text = typeof delta.content === 'string' ? delta.content : '';
445
+ if (text) {
446
+ reply += text;
447
+ if (onChunk) onChunk(text, reply);
440
448
  }
441
449
  }
450
+ reply = stripThinkBlocks(reply);
451
+ if (!reply) {
452
+ logger.warn('[processMultimodal] 流式响应内容为空,尝试非流式回退');
453
+ const response = await this.provider.chat({ model: visionModel, messages });
454
+ const msg = response.choices[0]?.message?.content;
455
+ reply = stripThinkBlocks(typeof msg === 'string' ? msg : '');
456
+ }
442
457
  } catch {
443
458
  const response = await this.provider.chat({ model: visionModel, messages });
444
459
  const msg = response.choices[0]?.message?.content;
445
- reply = typeof msg === 'string' ? msg : '';
460
+ reply = stripThinkBlocks(typeof msg === 'string' ? msg : '');
446
461
  }
447
462
 
448
463
  if (!reply) reply = '抱歉,我无法理解这条消息。';
@@ -474,20 +489,27 @@ ${preData ? `\nPre-fetched data:\n${preData}\n` : ''}`;
474
489
  try {
475
490
  let result = '';
476
491
  for await (const chunk of this.provider.chatStream({ model, messages })) {
477
- const delta = chunk.choices?.[0]?.delta?.content;
478
- if (delta && typeof delta === 'string') {
479
- result += delta;
480
- if (onChunk) onChunk(delta, result);
492
+ const delta = chunk.choices?.[0]?.delta;
493
+ if (!delta) continue;
494
+ const text = typeof delta.content === 'string' ? delta.content : '';
495
+ if (text) {
496
+ result += text;
497
+ if (onChunk) onChunk(text, result);
481
498
  }
482
499
  }
483
- return result;
500
+ result = stripThinkBlocks(result);
501
+ if (result) return result;
502
+ // Streaming returned empty content — fall back to non-streaming
503
+ logger.warn('[streamChat] 流式响应内容为空,尝试非流式回退');
484
504
  } catch {
485
- const response = await this.provider.chat({ model, messages });
486
- const msg = response.choices[0]?.message?.content;
487
- const result = typeof msg === 'string' ? msg : '';
488
- if (onChunk && result) onChunk(result, result);
489
- return result;
505
+ // Stream failed fall back to non-streaming
490
506
  }
507
+ const response = await this.provider.chat({ model, messages });
508
+ const msg = response.choices[0]?.message?.content;
509
+ let result = typeof msg === 'string' ? msg : '';
510
+ result = stripThinkBlocks(result);
511
+ if (onChunk && result) onChunk(result, result);
512
+ return result;
491
513
  }
492
514
 
493
515
  private async saveToSession(
@@ -5,7 +5,7 @@
5
5
  import { Logger } from '@zhin.js/core';
6
6
  import type { Tool, ToolContext, SkillFeature } from '@zhin.js/core';
7
7
  import type { AgentTool } from '@zhin.js/core';
8
- import { Agent } from '../agent.js';
8
+ import { Agent } from '@zhin.js/ai';
9
9
  import type { ZhinAgentConfig } from './config.js';
10
10
  import { PERM_MAP } from './config.js';
11
11