metame-cli 1.5.20 → 1.5.22

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/README.md CHANGED
@@ -614,12 +614,13 @@ Level mapping:
614
614
 
615
615
  ## Hook Optimizations (Default On)
616
616
 
617
- MetaMe installs and maintains core Claude hooks automatically on launch:
617
+ MetaMe keeps Claude hooks minimal and non-essential:
618
618
 
619
- - `UserPromptSubmit` hook (`scripts/hooks/intent-engine.js`): Unified intent engine for team dispatch, ops assist, and task creation hints.
620
619
  - `UserPromptSubmit` hook (`scripts/signal-capture.js`): captures high-signal preference/task traces with layered filtering.
621
620
  - `Stop` hook (`scripts/hooks/stop-session-capture.js`): records session-end/tool-failure signals with watermark protection.
622
621
 
622
+ Semantic intent recognition and prompt hint injection now run only inside the daemon runtime, so Claude and Codex share the same injection path.
623
+
623
624
  If hook installation fails, MetaMe logs and continues the session (non-blocking fallback).
624
625
 
625
626
  ## How It Works
package/index.js CHANGED
@@ -756,12 +756,17 @@ function ensureHookInstalled() {
756
756
  console.log(`${icon("hook")} MetaMe: Stop session capture hook installed.`);
757
757
  }
758
758
 
759
- // Migrate: remove standalone team-context.js hook (superseded by intent-engine)
759
+ // Migrate: remove obsolete semantic injection hooks.
760
+ // Intent routing now happens only inside the daemon runtime so Claude/Codex
761
+ // share one platform-agnostic path.
760
762
  if (settings.hooks?.UserPromptSubmit) {
761
763
  const before = settings.hooks.UserPromptSubmit.length;
762
764
  for (const entry of settings.hooks.UserPromptSubmit) {
763
765
  if (entry.hooks) {
764
- entry.hooks = entry.hooks.filter(h => !(h.command && h.command.includes('team-context.js')));
766
+ entry.hooks = entry.hooks.filter((h) => {
767
+ const cmd = h && h.command ? String(h.command) : '';
768
+ return !(cmd.includes('team-context.js') || cmd.includes('intent-engine.js'));
769
+ });
765
770
  }
766
771
  }
767
772
  settings.hooks.UserPromptSubmit = settings.hooks.UserPromptSubmit.filter(
@@ -770,27 +775,6 @@ function ensureHookInstalled() {
770
775
  if (settings.hooks.UserPromptSubmit.length !== before) modified = true;
771
776
  }
772
777
 
773
- // Ensure intent-engine hook (unified intent detection + hint injection)
774
- const intentEngineScript = path.join(METAME_DIR, 'hooks', 'intent-engine.js').replace(/\\/g, '/');
775
- const intentEngineCommand = `node "${intentEngineScript}"`;
776
- const intentEngineInstalled = (settings.hooks?.UserPromptSubmit || []).some(entry =>
777
- entry.hooks?.some(h => h.command && h.command.includes('intent-engine.js'))
778
- );
779
-
780
- if (!intentEngineInstalled) {
781
- if (!settings.hooks) settings.hooks = {};
782
- if (!settings.hooks.UserPromptSubmit) settings.hooks.UserPromptSubmit = [];
783
-
784
- settings.hooks.UserPromptSubmit.push({
785
- hooks: [{
786
- type: 'command',
787
- command: intentEngineCommand,
788
- }]
789
- });
790
- modified = true;
791
- console.log(`${icon("hook")} MetaMe: Intent engine hook installed.`);
792
- }
793
-
794
778
  if (modified) {
795
779
  fs.writeFileSync(CLAUDE_SETTINGS, JSON.stringify(settings, null, 2), 'utf8');
796
780
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "metame-cli",
3
- "version": "1.5.20",
3
+ "version": "1.5.22",
4
4
  "description": "The Cognitive Profile Layer for Claude Code. Knows how you think, not just what you said.",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -0,0 +1,111 @@
1
+ 'use strict';
2
+
3
+ function extractPathFromText(input) {
4
+ const text = String(input || '');
5
+ const unixMatch = text.match(/(?:~\/|\/|\.\/|\.\.\/)[^\s,。;;!!??"“”'‘’`]+/);
6
+ if (unixMatch) return unixMatch[0].replace(/[,。;;!!??]+$/, '');
7
+
8
+ const windowsMatch = text.match(/[A-Za-z]:[\\/][^\s,。;;!!??"“”'‘’`]+/);
9
+ if (windowsMatch) return windowsMatch[0].replace(/[,。;;!!??]+$/, '');
10
+
11
+ return '';
12
+ }
13
+
14
+ function detectCloneIntent(text) {
15
+ if (!text || text.startsWith('/') || text.length < 3) return false;
16
+ const cloneKeywords = ['分身', '再造', '克隆', '副本', '另一个自己', '另一个我'];
17
+ const hasCloneKeyword = cloneKeywords.some(k => text.includes(k));
18
+ if (hasCloneKeyword) {
19
+ const excludePatterns = [/已经/, /存在/, /有了/, /好了/, /完成/, /搞定/, /配置好/, /怎么建/, /如何建/, /方法/, /步骤/];
20
+ if (excludePatterns.some(p => p.test(text))) return false;
21
+ return true;
22
+ }
23
+ const actionKeywords = ['新建', '创建', '造', '做一个', '加一个', '增加', '添加'];
24
+ const hasAction = actionKeywords.some(k => text.includes(k));
25
+ if (hasAction && /分身|数字/.test(text)) return true;
26
+ if (/让.*做分身|叫.*做分身|甲.*做分身/.test(text)) return true;
27
+ return false;
28
+ }
29
+
30
+ function detectTeamIntent(text) {
31
+ if (!text || text.startsWith('/') || text.length < 4) return false;
32
+ if (/走team|用team|通过team|team里|team中|团队里|团队中|走团队|用团队|在team|在团队|team.*已经|团队.*已经|team.*讨论|团队.*讨论/.test(text)) return false;
33
+ if ((text.includes('团队') || text.includes('工作组'))) {
34
+ if (/(新建|创建|造一个|加一个|组建|设置|建|搞)/.test(text)) {
35
+ if (/怎么|如何|方法|步骤/.test(text)) return false;
36
+ return true;
37
+ }
38
+ }
39
+ if (/^(新建|创建|建|搞).*团队/.test(text)) return true;
40
+ return false;
41
+ }
42
+
43
+ function isLikelyDirectAgentAction(input) {
44
+ const text = String(input || '').trim();
45
+ return /^(?:请|帮我|麻烦|给我|给这个群|给当前群|在这个群|把这个群|把当前群|将这个群|这个群|当前群|本群|群里|我想|我要|我需要|创建|新建|新增|搞一个|加一个|create|bind|绑定|列出|查看|显示|有哪些|解绑|取消绑定|断开绑定|修改|调整)/i.test(text);
46
+ }
47
+
48
+ function looksLikeAgentIssueReport(input) {
49
+ const text = String(input || '').trim();
50
+ const hasIssueWords = /(用户反馈|反馈|报错|bug|问题|故障|异常|修复|改一下|修一下|任务|工单|代码)/i.test(text);
51
+ const hasAgentWords = /(agent|智能体|session|会话|目录|工作区|绑定|切换)/i.test(text);
52
+ return hasIssueWords && hasAgentWords;
53
+ }
54
+
55
+ function classifyAgentIntent(input) {
56
+ const text = String(input || '').trim();
57
+ if (!text || text.startsWith('/')) return null;
58
+
59
+ const workspaceDir = extractPathFromText(text);
60
+ const hasWorkspacePath = !!workspaceDir;
61
+ const directAction = isLikelyDirectAgentAction(text);
62
+ const issueReport = looksLikeAgentIssueReport(text);
63
+ if (issueReport && !directAction) return null;
64
+
65
+ const hasThirdPartyName = /(阿里|百度|腾讯|字节|谷歌|google|openai|微软|microsoft|deepseek|豆包|通义|文心|kimi)/i.test(text);
66
+ const hasAgentWord = /(智能体|agent|助手|机器人)/i.test(text);
67
+ const isAboutOurAgents = /(我的|我们的|当前|这个群|这里的|metame)/i.test(text);
68
+ if (hasThirdPartyName && hasAgentWord && !isAboutOurAgents) return null;
69
+
70
+ const hasAgentContext = /(agent|智能体|工作区|人设|绑定|当前群|这个群|chat|workspace)/i.test(text);
71
+ const wantsList = /(列出|查看|显示|有哪些|list|show)/i.test(text) && /(agent|智能体|工作区|绑定)/i.test(text);
72
+ const wantsUnbind = /(解绑|取消绑定|断开绑定|unbind|unassign)/i.test(text) && hasAgentContext;
73
+ const wantsEditRole =
74
+ ((/(角色|职责|人设)/i.test(text) && /(改|修改|调整|更新|变成|改成|改为)/i.test(text)) ||
75
+ /(把这个agent|把当前agent|当前群.*角色|当前群.*职责)/i.test(text));
76
+ const wantsCreate =
77
+ (/(创建|新建|新增|搞一个|加一个|create)/i.test(text) && /(agent|智能体|人设|工作区)/i.test(text) && (directAction || hasWorkspacePath));
78
+ const wantsBind =
79
+ !wantsCreate &&
80
+ (/(绑定|bind)/i.test(text) && hasAgentContext && (directAction || hasWorkspacePath));
81
+ const wantsActivate = /(?:在新群|新群里|新群中|目标群|另一个群).{0,12}(激活|activate)|(?:激活|activate).{0,12}(agent|智能体|绑定)|\/activate/i.test(text);
82
+ const wantsReset =
83
+ /(重置|清空|删除).{0,24}(agent|智能体|助手|角色|职责|人设).{0,12}(角色|职责|人设)?/i.test(text) ||
84
+ /(?:角色|职责|人设).{0,12}(重置|清空|删除)/i.test(text) ||
85
+ /\/agent reset/i.test(text);
86
+ const wantsSoul = /(soul|灵魂|身份设定|人格设定)/i.test(text) && /(查看|修复|编辑|修改|更新|repair|edit|show|看)/i.test(text);
87
+ const wantsAgentDoc =
88
+ /(?:agent|智能体|机器人|bot).{0,12}(文档|手册|说明|guide)/i.test(text) ||
89
+ /(?:怎么|如何|手册|文档|说明).{0,12}(配置|管理|使用).{0,12}(agent|智能体|机器人|bot)/i.test(text) ||
90
+ /(?:agent|智能体|机器人|bot).{0,12}(怎么|如何).{0,12}(配置|管理|使用)/i.test(text);
91
+
92
+ if (wantsList) return { action: 'list', workspaceDir };
93
+ if (wantsUnbind) return { action: 'unbind', workspaceDir };
94
+ if (wantsEditRole) return { action: 'edit_role', workspaceDir };
95
+ if (wantsCreate) return { action: 'create', workspaceDir };
96
+ if (wantsBind) return { action: 'bind', workspaceDir };
97
+ if (wantsAgentDoc) return { action: 'agent_doc', workspaceDir };
98
+ if (wantsActivate) return { action: 'activate', workspaceDir };
99
+ if (wantsReset) return { action: 'reset', workspaceDir };
100
+ if (wantsSoul) return { action: 'soul', workspaceDir };
101
+ if (detectCloneIntent(text)) return { action: 'wizard_clone', workspaceDir };
102
+ if (detectTeamIntent(text)) return { action: 'wizard_team', workspaceDir };
103
+ return null;
104
+ }
105
+
106
+ module.exports = {
107
+ classifyAgentIntent,
108
+ detectCloneIntent,
109
+ detectTeamIntent,
110
+ extractPathFromText,
111
+ };