mumucc 0.1.8 → 0.2.0

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/.gitignore.bak ADDED
@@ -0,0 +1,11 @@
1
+ node_modules/
2
+ .env
3
+ .env.*
4
+ !.env
5
+ .env.local
6
+ .env.local.*
7
+ *.log
8
+ .DS_Store
9
+ dist/
10
+ .claude/projects/
11
+ bin/
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mumucc",
3
- "version": "0.1.8",
3
+ "version": "0.2.0",
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",
@@ -28,6 +28,9 @@ const DEFAULT_ENABLED: Set<string> = new Set([
28
28
  'HOOK_PROMPTS',
29
29
  'DOWNLOAD_USER_SETTINGS',
30
30
  'UPLOAD_USER_SETTINGS',
31
+ 'KAIROS', // mumucc: 启用 channels/proactive 功能
32
+ 'KAIROS_CHANNELS', // mumucc: 启用 channels 支持
33
+ 'PROACTIVE', // mumucc: 启用 proactive 功能
31
34
  ])
32
35
 
33
36
  // Parse env override
package/shims/globals.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  ;(globalThis as any).MACRO = {
7
- VERSION: '0.1.8-mumucc',
7
+ VERSION: '0.1.9-mumucc',
8
8
  VERSION_CHANGELOG: '{}',
9
9
  BUILD_TIME: new Date().toISOString(),
10
10
  PACKAGE_URL: 'https://github.com/mumuxsy/mumucc',
package/src/cli/print.ts CHANGED
@@ -4671,9 +4671,7 @@ function handleChannelEnable(
4671
4671
  response: { subtype: 'error', request_id: requestId, error },
4672
4672
  })
4673
4673
 
4674
- if (!(feature('KAIROS') || feature('KAIROS_CHANNELS'))) {
4675
- return respondError('channels feature not available in this build')
4676
- }
4674
+ // mumucc: channels 已强制启用,不再检查 feature flag
4677
4675
 
4678
4676
  // Only a 'connected' client has .capabilities and .client to register the
4679
4677
  // handler on. The pool spread at the call site matches mcp_status.
@@ -43,7 +43,7 @@ export function ChannelsNotice() {
43
43
  }
44
44
  let t2;
45
45
  if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
46
- t2 = <Text dimColor={true}>Channels are not currently available</Text>;
46
+ t2 = <Text dimColor={true}>Channels 初始化中...</Text>; // mumucc: 友好提示
47
47
  $[3] = t2;
48
48
  } else {
49
49
  t2 = $[3];
@@ -70,7 +70,7 @@ export function ChannelsNotice() {
70
70
  }
71
71
  let t2;
72
72
  if ($[9] === Symbol.for("react.memo_cache_sentinel")) {
73
- t2 = <Text dimColor={true}>Channels require claude.ai authentication · run /login, then restart</Text>;
73
+ t2 = <Text dimColor={true}>Channels 可通过 API key OAuth 使用</Text>; // mumucc: 移除 OAuth 强制要求
74
74
  $[9] = t2;
75
75
  } else {
76
76
  t2 = $[9];
@@ -99,7 +99,7 @@ export function ChannelsNotice() {
99
99
  let t3;
100
100
  if ($[15] === Symbol.for("react.memo_cache_sentinel")) {
101
101
  t2 = <Text dimColor={true}>Inbound messages will be silently dropped</Text>;
102
- t3 = <Text dimColor={true}>Have an administrator set channelsEnabled: true in managed settings to enable</Text>;
102
+ t3 = <Text dimColor={true}>Channels 已启用 (mumucc)</Text>; // mumucc: 去掉管理员设置提示
103
103
  $[15] = t2;
104
104
  $[16] = t3;
105
105
  } else {
@@ -263,7 +263,7 @@ export async function showSetupScreens(root: Root, permissionMode: PermissionMod
263
263
  // named. dev:true here is for the flag label in ChannelsNotice
264
264
  // (hasNonDev check); the allowlist bypass it also grants is moot
265
265
  // since the gate blocks upstream.
266
- if (!isChannelsEnabled() || !getClaudeAIOAuthTokens()?.accessToken) {
266
+ if (false) { // mumucc: 跳过 channels 禁用检查,直接显示确认对话框
267
267
  setAllowedChannels([...getAllowedChannels(), ...devChannels.map(c => ({
268
268
  ...c,
269
269
  dev: true
package/src/main.tsx CHANGED
@@ -1681,9 +1681,10 @@ async function run(): Promise<CommanderCommand> {
1681
1681
  const channelOpts = options as {
1682
1682
  channels?: string[];
1683
1683
  dangerouslyLoadDevelopmentChannels?: string[];
1684
+ channelsDev?: string[]; // mumucc: 短别名
1684
1685
  };
1685
1686
  const rawChannels = channelOpts.channels;
1686
- const rawDev = channelOpts.dangerouslyLoadDevelopmentChannels;
1687
+ const rawDev = channelOpts.dangerouslyLoadDevelopmentChannels ?? channelOpts.channelsDev; // mumucc: 支持短别名
1687
1688
  // Always parse + set. ChannelsNotice reads getAllowedChannels() and
1688
1689
  // renders the appropriate branch (disabled/noAuth/policyBlocked/
1689
1690
  // listening) in the startup screen. gateChannelServer() enforces.
@@ -3844,6 +3845,7 @@ async function run(): Promise<CommanderCommand> {
3844
3845
  if (feature('KAIROS') || feature('KAIROS_CHANNELS')) {
3845
3846
  program.addOption(new Option('--channels <servers...>', 'MCP servers whose channel notifications (inbound push) should register this session. Space-separated server names.').hideHelp());
3846
3847
  program.addOption(new Option('--dangerously-load-development-channels <servers...>', 'Load channel servers not on the approved allowlist. For local channel development only. Shows a confirmation dialog at startup.').hideHelp());
3848
+ program.addOption(new Option('--channels-dev <servers...>', 'mumucc: --dangerously-load-development-channels 的短别名').hideHelp()); // mumucc: 短别名
3847
3849
  }
3848
3850
 
3849
3851
  // Teammate identity options (set by leader when spawning tmux teammates)
@@ -49,7 +49,7 @@ export function getChannelAllowlist(): ChannelAllowlistEntry[] {
49
49
  * Default false; GrowthBook 5-min refresh.
50
50
  */
51
51
  export function isChannelsEnabled(): boolean {
52
- return getFeatureValue_CACHED_MAY_BE_STALE('tengu_harbor', false)
52
+ return true // mumucc: 强制启用 channels
53
53
  }
54
54
 
55
55
  /**
@@ -205,44 +205,11 @@ export function gateChannelServer(
205
205
  }
206
206
  }
207
207
 
208
- // Overall runtime gate. After capability so normal MCP servers never hit
209
- // this path. Before auth/policy so the killswitch works regardless of
210
- // session state.
211
- if (!isChannelsEnabled()) {
212
- return {
213
- action: 'skip',
214
- kind: 'disabled',
215
- reason: 'channels feature is not currently available',
216
- }
217
- }
218
-
219
- // OAuth-only. API key users (console) are blocked — there's no
220
- // channelsEnabled admin surface in console yet, so the policy opt-in
221
- // flow doesn't exist for them. Drop this when console parity lands.
222
- if (!getClaudeAIOAuthTokens()?.accessToken) {
223
- return {
224
- action: 'skip',
225
- kind: 'auth',
226
- reason: 'channels requires claude.ai authentication (run /login)',
227
- }
228
- }
229
-
230
- // Teams/Enterprise opt-in. Managed orgs must explicitly enable channels.
231
- // Default OFF — absent or false blocks. Keyed off subscription tier, not
232
- // "policy settings exist" — a team org with zero configured policy keys
233
- // (remote endpoint returns 404) is still a managed org and must not fall
234
- // through to the unmanaged path.
208
+ // mumucc: 跳过 runtime gate、OAuth 检查和 Team/Enterprise 策略检查
209
+ // API key 模式和所有用户都能使用 channels
235
210
  const sub = getSubscriptionType()
236
211
  const managed = sub === 'team' || sub === 'enterprise'
237
212
  const policy = managed ? getSettingsForSource('policySettings') : undefined
238
- if (managed && policy?.channelsEnabled !== true) {
239
- return {
240
- action: 'skip',
241
- kind: 'policy',
242
- reason:
243
- 'channels not enabled by org policy (set channelsEnabled: true in managed settings)',
244
- }
245
- }
246
213
 
247
214
  // User-level session opt-in. A server must be explicitly listed in
248
215
  // --channels to push inbound this session — protects against a trusted
@@ -256,61 +223,8 @@ export function gateChannelServer(
256
223
  }
257
224
  }
258
225
 
259
- if (entry.kind === 'plugin') {
260
- // Marketplace verification: the tag is intent (plugin:slack@anthropic),
261
- // the runtime name is just plugin:slack:X — could be slack@anthropic or
262
- // slack@evil depending on what's installed. Verify they match before
263
- // trusting the tag for the allowlist check below. Source is stashed on
264
- // the config at addPluginScopeToServers — undefined (non-plugin server,
265
- // shouldn't happen for plugin-kind entry) or @-less (builtin/inline)
266
- // both fail the comparison.
267
- const actual = pluginSource
268
- ? parsePluginIdentifier(pluginSource).marketplace
269
- : undefined
270
- if (actual !== entry.marketplace) {
271
- return {
272
- action: 'skip',
273
- kind: 'marketplace',
274
- reason: `you asked for plugin:${entry.name}@${entry.marketplace} but the installed ${entry.name} plugin is from ${actual ?? 'an unknown source'}`,
275
- }
276
- }
277
-
278
- // Approved-plugin allowlist. Marketplace gate already verified
279
- // tag == reality, so this is a pure entry check. entry.dev (per-entry,
280
- // not the session-wide bit) bypasses — so accepting the dev dialog for
281
- // one entry doesn't leak allowlist-bypass to --channels entries.
282
- if (!entry.dev) {
283
- const { entries, source } = getEffectiveChannelAllowlist(
284
- sub,
285
- policy?.allowedChannelPlugins,
286
- )
287
- if (
288
- !entries.some(
289
- e => e.plugin === entry.name && e.marketplace === entry.marketplace,
290
- )
291
- ) {
292
- return {
293
- action: 'skip',
294
- kind: 'allowlist',
295
- reason:
296
- source === 'org'
297
- ? `plugin ${entry.name}@${entry.marketplace} is not on your org's approved channels list (set allowedChannelPlugins in managed settings)`
298
- : `plugin ${entry.name}@${entry.marketplace} is not on the approved channels allowlist (use --dangerously-load-development-channels for local dev)`,
299
- }
300
- }
301
- }
302
- } else {
303
- // server-kind: allowlist schema is {marketplace, plugin} — a server entry
304
- // can never match. Without this, --channels server:plugin:foo:bar would
305
- // match a plugin's runtime name and register with no allowlist check.
306
- if (!entry.dev) {
307
- return {
308
- action: 'skip',
309
- kind: 'allowlist',
310
- reason: `server ${entry.name} is not on the approved channels allowlist (use --dangerously-load-development-channels for local dev)`,
311
- }
312
- }
313
- }
226
+ // mumucc: 跳过 marketplace 验证和 allowlist 检查,允许所有 channel 服务器注册
227
+ // 原始代码在此处检查 plugin marketplace 匹配和 allowlist,对于自建 fork 不需要
314
228
 
315
229
  return { action: 'register' }
316
230
  }
@@ -34,7 +34,7 @@ import { getFeatureValue_CACHED_MAY_BE_STALE } from '../analytics/growthbook.js'
34
34
  * don't apply until restart.
35
35
  */
36
36
  export function isChannelPermissionRelayEnabled(): boolean {
37
- return getFeatureValue_CACHED_MAY_BE_STALE('tengu_harbor_permissions', false)
37
+ return true // mumucc: 强制启用 channel permission relay
38
38
  }
39
39
 
40
40
  export type ChannelPermissionResponse = {
package/src/utils/env.ts CHANGED
@@ -22,7 +22,10 @@ export const getGlobalClaudeFile = memoize((): string => {
22
22
  }
23
23
 
24
24
  const filename = `.mumucc${fileSuffixForOauthConfig()}.json`
25
- return join(process.env.CLAUDE_CONFIG_DIR || homedir(), filename)
25
+ // Always keep global config inside the mumucc config dir (~/.mumucc/.mumucc.json)
26
+ // to avoid polluting HOME root and to prevent any overlap with standard Claude Code
27
+ // config (~/.claude.json). CLAUDE_CONFIG_DIR override is still respected.
28
+ return join(process.env.CLAUDE_CONFIG_DIR || getClaudeConfigHomeDir(), filename)
26
29
  })
27
30
 
28
31
  const hasInternetAccess = memoize(async (): Promise<boolean> => {