mumucc 0.3.1 → 0.4.1
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/bin/mumuclaw +154 -0
- package/package.json +3 -2
- package/src/services/api/client.ts +13 -4
- package/src/utils/logoV2Utils.ts +6 -6
- package/src/utils/model/modelOptions.ts +3 -0
package/bin/mumuclaw
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ────────────────────────────────────────────────────────────────
|
|
3
|
+
# mumuclaw — AI Agent 守护平台(OpenClaw 替代品)
|
|
4
|
+
#
|
|
5
|
+
# 基于 mumucc,默认启用:
|
|
6
|
+
# - Channels(微信/心跳/自定义通道)
|
|
7
|
+
# - 所有 MCP 工具权限
|
|
8
|
+
# - 心跳 channel(GLM-5-turbo 预筛选)
|
|
9
|
+
# - 微信 wechat_reply 自动批准
|
|
10
|
+
#
|
|
11
|
+
# 用法:
|
|
12
|
+
# mumuclaw # 交互模式
|
|
13
|
+
# mumuclaw --daemon # 守护进程模式(无 TTY)
|
|
14
|
+
# mumuclaw --model glm # 指定模型预设
|
|
15
|
+
# mumuclaw --model minimax # MiniMax 预设
|
|
16
|
+
# mumuclaw --model claude # Claude Sonnet(默认)
|
|
17
|
+
# ────────────────────────────────────────────────────────────────
|
|
18
|
+
|
|
19
|
+
set -euo pipefail
|
|
20
|
+
|
|
21
|
+
SCRIPT_PATH="$(cd "$(dirname "$(readlink -f "$0" 2>/dev/null || python3 -c "import os,sys; print(os.path.realpath(sys.argv[1]))" "$0")")" && pwd)"
|
|
22
|
+
PROJECT_ROOT="$(dirname "$SCRIPT_PATH")"
|
|
23
|
+
|
|
24
|
+
# ── 模型预设 ──
|
|
25
|
+
MODEL_PRESET="claude"
|
|
26
|
+
EXTRA_ARGS=()
|
|
27
|
+
|
|
28
|
+
# 解析 mumuclaw 专属参数
|
|
29
|
+
while [[ $# -gt 0 ]]; do
|
|
30
|
+
case "$1" in
|
|
31
|
+
--model)
|
|
32
|
+
MODEL_PRESET="$2"
|
|
33
|
+
shift 2
|
|
34
|
+
;;
|
|
35
|
+
--daemon)
|
|
36
|
+
DAEMON_MODE=1
|
|
37
|
+
shift
|
|
38
|
+
;;
|
|
39
|
+
*)
|
|
40
|
+
EXTRA_ARGS+=("$1")
|
|
41
|
+
shift
|
|
42
|
+
;;
|
|
43
|
+
esac
|
|
44
|
+
done
|
|
45
|
+
|
|
46
|
+
case "$MODEL_PRESET" in
|
|
47
|
+
glm|glm-5-turbo)
|
|
48
|
+
export ANTHROPIC_BASE_URL="https://open.bigmodel.cn/api/anthropic"
|
|
49
|
+
export ANTHROPIC_AUTH_TOKEN="fb1c93822c2947d3b84019d1f6c525ee.fnpWi89jlC6IxPLQ"
|
|
50
|
+
# mumucc: 不再清空 ANTHROPIC_API_KEY,保留 claude.ai 登录态以支持 /model 切换到 Claude
|
|
51
|
+
export ANTHROPIC_DEFAULT_SONNET_MODEL="${GLM_MODEL:-glm-5-turbo}"
|
|
52
|
+
export ANTHROPIC_DEFAULT_OPUS_MODEL="${GLM_MODEL:-glm-5-turbo}"
|
|
53
|
+
export ANTHROPIC_DEFAULT_HAIKU_MODEL="${GLM_MODEL:-glm-5-turbo}"
|
|
54
|
+
;;
|
|
55
|
+
glm-5.1)
|
|
56
|
+
export ANTHROPIC_BASE_URL="https://open.bigmodel.cn/api/anthropic"
|
|
57
|
+
export ANTHROPIC_AUTH_TOKEN="fb1c93822c2947d3b84019d1f6c525ee.fnpWi89jlC6IxPLQ"
|
|
58
|
+
# mumucc: 不再清空 ANTHROPIC_API_KEY,保留 claude.ai 登录态以支持 /model 切换到 Claude
|
|
59
|
+
export ANTHROPIC_DEFAULT_SONNET_MODEL="glm-5.1"
|
|
60
|
+
export ANTHROPIC_DEFAULT_OPUS_MODEL="glm-5.1"
|
|
61
|
+
export ANTHROPIC_DEFAULT_HAIKU_MODEL="glm-5.1"
|
|
62
|
+
;;
|
|
63
|
+
minimax|m2.7)
|
|
64
|
+
export ANTHROPIC_BASE_URL="https://api.minimaxi.com/anthropic"
|
|
65
|
+
export ANTHROPIC_AUTH_TOKEN="sk-cp-rWK5pwrquDncnYIfVknvMNEBDvMR7-xPOtg5SBX9erW3_hkPUJhU6qYoZRzStCTqBppfvK4AVj4OPCpCICtScSm-_5obP48cEl8MwchmA0A5eo8kE3Vt4Dw"
|
|
66
|
+
# mumucc: 不再清空 ANTHROPIC_API_KEY,保留 claude.ai 登录态以支持 /model 切换到 Claude
|
|
67
|
+
export ANTHROPIC_DEFAULT_SONNET_MODEL="${MINIMAX_MODEL:-MiniMax-M2.7-highspeed}"
|
|
68
|
+
export ANTHROPIC_DEFAULT_OPUS_MODEL="${MINIMAX_MODEL:-MiniMax-M2.7-highspeed}"
|
|
69
|
+
export ANTHROPIC_DEFAULT_HAIKU_MODEL="${MINIMAX_MODEL:-MiniMax-M2.7-highspeed}"
|
|
70
|
+
;;
|
|
71
|
+
claude|sonnet)
|
|
72
|
+
# mumucc: 确保使用 claude.ai OAuth,清除所有第三方 provider 配置
|
|
73
|
+
# isAnthropicAuthEnabled() 检测到 ANTHROPIC_AUTH_TOKEN 存在时会禁用 OAuth
|
|
74
|
+
unset ANTHROPIC_AUTH_TOKEN
|
|
75
|
+
unset ANTHROPIC_BASE_URL
|
|
76
|
+
# 清除模型覆盖,防止上次 GLM/MiniMax 会话的 "glm-5-turbo" 被发到 Anthropic API
|
|
77
|
+
unset ANTHROPIC_DEFAULT_SONNET_MODEL
|
|
78
|
+
unset ANTHROPIC_DEFAULT_OPUS_MODEL
|
|
79
|
+
unset ANTHROPIC_DEFAULT_HAIKU_MODEL
|
|
80
|
+
;;
|
|
81
|
+
*)
|
|
82
|
+
echo "mumuclaw: 未知模型预设 '$MODEL_PRESET'"
|
|
83
|
+
echo "可用: glm, glm-5.1, minimax, claude"
|
|
84
|
+
exit 1
|
|
85
|
+
;;
|
|
86
|
+
esac
|
|
87
|
+
|
|
88
|
+
export API_TIMEOUT_MS=${API_TIMEOUT_MS:-300000}
|
|
89
|
+
|
|
90
|
+
# ── 代理配置(中国大陆访问 Anthropic API 需要)──
|
|
91
|
+
export https_proxy="${https_proxy:-http://127.0.0.1:7890}"
|
|
92
|
+
export http_proxy="${http_proxy:-http://127.0.0.1:7890}"
|
|
93
|
+
export ALL_PROXY="${ALL_PROXY:-http://127.0.0.1:7890}"
|
|
94
|
+
|
|
95
|
+
# ── mumuclaw agent 系统提示词(追加到默认提示词之后)──
|
|
96
|
+
AGENT_PROMPT='���运行在 mumuclaw 守护模式���—一个 7x24 在线的 AI Agent 平台。
|
|
97
|
+
|
|
98
|
+
## 运���模式
|
|
99
|
+
- 你是一个自主 agent,不是交互式编码助手
|
|
100
|
+
- 通过 channel 接收外部事件���微信消息、心跳、cron 任务)
|
|
101
|
+
- 所有���用户的交互通过 mcp__wechat__wechat_reply 工具完成(发给指定 sender_id)
|
|
102
|
+
- 终端��出无人查看,不要依赖终端展示信息
|
|
103
|
+
- 微��消息���须用纯文本(不��持 Markdown),用「」或【】��强调
|
|
104
|
+
|
|
105
|
+
## 事件处理
|
|
106
|
+
- <channel source="wechat"> — 微信消息,立即处理并通过 wechat_reply 回复
|
|
107
|
+
- <channel source="heartbeat" type="heartbeat"> — 定时心跳,检���状态、做自主工作
|
|
108
|
+
- <channel source="heartbeat" type="glm_escalation"> — GLM 判定需��你处理的事项
|
|
109
|
+
- <channel source="heartbeat" type="cron_task"> — cron 定时任务,按内容执行并通过微信汇报
|
|
110
|
+
- <channel source="heartbeat" type="startup"> — 启动事件,读取记忆初始化状态
|
|
111
|
+
|
|
112
|
+
## 自主行为
|
|
113
|
+
- 没有外���事件时也保持活跃:整理记忆、检��项目、准备素材
|
|
114
|
+
- 有能力 SSH 到其他设备、上网搜索、读写文件、运行脚本
|
|
115
|
+
- 主动推进少洋的项目,��等指令
|
|
116
|
+
- 记录工作状��到 ~/.openclaw/workspace/.heartbeat-state.json
|
|
117
|
+
|
|
118
|
+
## 记忆系统
|
|
119
|
+
- 长期记忆:~/.openclaw/workspace/MEMORY.md
|
|
120
|
+
- 每日日记:~/.openclaw/workspace/memory/YYYY-MM-DD.md
|
|
121
|
+
- 工作��程:~/.openclaw/workspace/memory/procedures.md
|
|
122
|
+
- 每次启动和心跳都要参考记忆保持连续性'
|
|
123
|
+
|
|
124
|
+
# ── mumuclaw 默认启用的 channel servers ──
|
|
125
|
+
# 从 .mcp.json 中读取可用的 channel servers
|
|
126
|
+
CHANNEL_SERVERS=""
|
|
127
|
+
MCP_JSON="$(pwd)/.mcp.json"
|
|
128
|
+
if [[ -f "$MCP_JSON" ]]; then
|
|
129
|
+
# 自动检测 .mcp.json 中声明的 channel servers
|
|
130
|
+
for server in wechat heartbeat; do
|
|
131
|
+
if python3 -c "import json; d=json.load(open('$MCP_JSON')); exit(0 if '$server' in d.get('mcpServers',{}) else 1)" 2>/dev/null; then
|
|
132
|
+
CHANNEL_SERVERS="$CHANNEL_SERVERS server:$server"
|
|
133
|
+
fi
|
|
134
|
+
done
|
|
135
|
+
fi
|
|
136
|
+
|
|
137
|
+
# ── 启动 ──
|
|
138
|
+
if [[ "${DAEMON_MODE:-}" = "1" ]] || [[ ! -t 0 ]]; then
|
|
139
|
+
# 守护模式:用 script 模拟 PTY
|
|
140
|
+
exec script -q /dev/null "$SCRIPT_PATH/mumucc" \
|
|
141
|
+
--dangerously-load-development-channels $CHANNEL_SERVERS \
|
|
142
|
+
--allowedTools "mcp__wechat__wechat_reply" \
|
|
143
|
+
--dangerously-skip-permissions \
|
|
144
|
+
--append-system-prompt "$AGENT_PROMPT" \
|
|
145
|
+
"${EXTRA_ARGS[@]}"
|
|
146
|
+
else
|
|
147
|
+
# 交互模式
|
|
148
|
+
exec "$SCRIPT_PATH/mumucc" \
|
|
149
|
+
--dangerously-load-development-channels $CHANNEL_SERVERS \
|
|
150
|
+
--allowedTools "mcp__wechat__wechat_reply" \
|
|
151
|
+
--dangerously-skip-permissions \
|
|
152
|
+
--append-system-prompt "$AGENT_PROMPT" \
|
|
153
|
+
"${EXTRA_ARGS[@]}"
|
|
154
|
+
fi
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mumucc",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Open-source AI coding assistant CLI with multi-model support (Anthropic, OpenAI/GPT, DeepSeek, GLM, Ollama, etc.), MCP integration, agent swarms, and out-of-the-box developer experience.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
"src/*": "./src/*"
|
|
28
28
|
},
|
|
29
29
|
"bin": {
|
|
30
|
-
"mumucc": "./bin/mumucc"
|
|
30
|
+
"mumucc": "./bin/mumucc",
|
|
31
|
+
"mumuclaw": "./bin/mumuclaw"
|
|
31
32
|
},
|
|
32
33
|
"scripts": {
|
|
33
34
|
"start": "bun run --preload ./shims/globals.ts src/main.tsx",
|
|
@@ -311,11 +311,20 @@ export async function getAnthropicClient({
|
|
|
311
311
|
}
|
|
312
312
|
|
|
313
313
|
// Determine authentication method based on available tokens
|
|
314
|
+
// mumucc: 检测当前模型是否为 Claude 原生模型
|
|
315
|
+
const isClaudeModel = model && (model.includes('claude') || model.includes('sonnet') || model.includes('opus') || model.includes('haiku'))
|
|
316
|
+
// 当设了第三方 BASE_URL 且当前不是 Claude 原生模型时,用第三方认证
|
|
317
|
+
const forceThirdPartyKey = !isClaudeModel && !!process.env.ANTHROPIC_AUTH_TOKEN && !!process.env.ANTHROPIC_BASE_URL
|
|
318
|
+
|
|
314
319
|
const clientConfig: ConstructorParameters<typeof Anthropic>[0] = {
|
|
315
|
-
apiKey:
|
|
316
|
-
|
|
317
|
-
?
|
|
318
|
-
|
|
320
|
+
apiKey: forceThirdPartyKey
|
|
321
|
+
? process.env.ANTHROPIC_AUTH_TOKEN // mumucc: 第三方 provider,用 AUTH_TOKEN 作为 x-api-key
|
|
322
|
+
: (isClaudeAISubscriber() ? null : apiKey || getAnthropicApiKey()),
|
|
323
|
+
authToken: forceThirdPartyKey
|
|
324
|
+
? undefined // mumucc: 第三方 provider,不用 OAuth
|
|
325
|
+
: (isClaudeAISubscriber() ? getClaudeAIOAuthTokens()?.accessToken : undefined),
|
|
326
|
+
// mumucc: Claude 原生模型时忽略第三方 BASE_URL,直接连 Anthropic API
|
|
327
|
+
...(forceThirdPartyKey ? {} : { baseURL: undefined }),
|
|
319
328
|
// Set baseURL from OAuth config when using staging OAuth
|
|
320
329
|
...(process.env.USER_TYPE === 'ant' &&
|
|
321
330
|
isEnvTruthy(process.env.USE_STAGING_OAUTH)
|
package/src/utils/logoV2Utils.ts
CHANGED
|
@@ -265,17 +265,17 @@ export function getLogoDisplayData(): {
|
|
|
265
265
|
// Use whichever subscription indicator is available
|
|
266
266
|
const effectiveSubscription = subscriptionType ?? (oauthAccountBillingType ? oauthAccountBillingType : null)
|
|
267
267
|
const providers = getThirdPartyProviders()
|
|
268
|
+
// mumucc: 只显示已认证(有 apiKey)的 provider,不显示未登录的
|
|
269
|
+
const authedProviders = providers.filter(p => p.apiKey && p.apiKey.length > 0)
|
|
268
270
|
|
|
269
271
|
let billingType: string
|
|
270
|
-
if (effectiveSubscription &&
|
|
271
|
-
// Both account subscription and third-party API
|
|
272
|
+
if (effectiveSubscription && authedProviders.length > 0) {
|
|
272
273
|
const subName = getSubscriptionName() || oauthAccountBillingType || 'Subscriber'
|
|
273
|
-
billingType = `${subName} + ${
|
|
274
|
+
billingType = `${subName} + ${authedProviders.map(p => p.name).join(', ')}`
|
|
274
275
|
} else if (effectiveSubscription) {
|
|
275
276
|
billingType = getSubscriptionName() || oauthAccountBillingType || 'Subscriber'
|
|
276
|
-
} else if (
|
|
277
|
-
|
|
278
|
-
billingType = providers.map(p => p.name).join(', ')
|
|
277
|
+
} else if (authedProviders.length > 0) {
|
|
278
|
+
billingType = authedProviders.map(p => p.name).join(', ')
|
|
279
279
|
} else {
|
|
280
280
|
billingType = 'API Usage Billing'
|
|
281
281
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { getInitialMainLoopModel } from '../../bootstrap/state.js'
|
|
3
3
|
import {
|
|
4
4
|
getAnthropicApiKey,
|
|
5
|
+
getClaudeAIOAuthTokens,
|
|
5
6
|
isClaudeAISubscriber,
|
|
6
7
|
isMaxSubscriber,
|
|
7
8
|
isTeamPremiumSubscriber,
|
|
@@ -274,8 +275,10 @@ function getModelOptionsBase(fastMode = false): ModelOption[] {
|
|
|
274
275
|
// If no Anthropic auth is configured (no API key, no OAuth token),
|
|
275
276
|
// skip Anthropic models entirely — user only sees third-party models
|
|
276
277
|
// from providers they've configured via /login.
|
|
278
|
+
// mumucc: 也检查 OAuth 登录态(claude.ai /login),不只看 API key
|
|
277
279
|
const hasAnthropicAuth =
|
|
278
280
|
!!getAnthropicApiKey() ||
|
|
281
|
+
!!getClaudeAIOAuthTokens()?.accessToken ||
|
|
279
282
|
!!process.env.CLAUDE_CODE_USE_BEDROCK ||
|
|
280
283
|
!!process.env.CLAUDE_CODE_USE_VERTEX ||
|
|
281
284
|
!!process.env.CLAUDE_CODE_USE_FOUNDRY
|