Skip to content

Commit db547d4

Browse files
refactor: 将 server.ts 迁入 packages/weixin,彻底移除 src/services/weixin/
通过依赖注入(WeixinServerDeps)解耦 src/ 依赖(analytics、config、 MCP channel schema),server.ts 完全移入包内。cli.tsx 入口处一次性 注入所有依赖。 src/services/weixin/ 目录已完全删除。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 40916a6 commit db547d4

5 files changed

Lines changed: 89 additions & 64 deletions

File tree

packages/weixin/src/cli.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { clearAccount, DEFAULT_BASE_URL, loadAccount, saveAccount } from './accounts.js'
22
import { startLogin, waitForLogin } from './login.js'
33
import { confirmPairing } from './pairing.js'
4+
import { runWeixinMcpServer } from './server.js'
5+
import type { WeixinServerDeps } from './server.js'
46

57
function printUsage(): void {
68
process.stdout.write(
@@ -92,18 +94,18 @@ function runAccess(args: string[]): void {
9294

9395
export async function handleWeixinCli(
9496
args: string[],
95-
serveHandler?: () => Promise<void>,
97+
serverDeps?: WeixinServerDeps,
98+
version?: string,
9699
): Promise<void> {
97100
const [subcommand, ...rest] = args
98101

99102
switch (subcommand) {
100103
case 'serve':
101-
if (serveHandler) {
102-
await serveHandler()
103-
} else {
104+
if (!serverDeps) {
104105
process.stderr.write('[weixin] serve handler not available in this context.\n')
105106
process.exit(1)
106107
}
108+
await runWeixinMcpServer(version ?? '0.0.0', serverDeps)
107109
return
108110
case 'login':
109111
await runLogin(rest[0] === 'clear')

packages/weixin/src/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,5 +107,9 @@ export type {
107107
ActivePermissionChat,
108108
} from './permissions.js'
109109

110+
// Server (MCP)
111+
export { createWeixinMcpServer, runWeixinMcpServer } from './server.js'
112+
export type { WeixinServerDeps } from './server.js'
113+
110114
// CLI
111115
export { handleWeixinCli } from './cli.js'
Lines changed: 60 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,6 @@ import {
55
CallToolRequestSchema,
66
ListToolsRequestSchema,
77
} from '@modelcontextprotocol/sdk/types.js'
8-
import {
9-
ChannelPermissionRequestNotificationSchema,
10-
type ChannelPermissionRequestParams,
11-
} from '../mcp/channelNotification.js'
12-
import { initializeAnalyticsSink } from '../analytics/sink.js'
13-
import { shutdownDatadog } from '../analytics/datadog.js'
14-
import { shutdown1PEventLogging } from '../analytics/firstPartyEventLogger.js'
15-
import { enableConfigs } from '../../utils/config.js'
16-
import { logForDebugging } from '../../utils/debug.js'
178
import {
189
CDN_BASE_URL,
1910
DEFAULT_BASE_URL,
@@ -27,8 +18,21 @@ import {
2718
sendMediaFile,
2819
sendText,
2920
TypingStatus,
30-
} from '@claude-code-best/weixin'
31-
import type { ParsedMessage } from '@claude-code-best/weixin'
21+
} from './index.js'
22+
import type { ParsedMessage } from './monitor.js'
23+
import type { ChannelPermissionRequestParams } from './permissions.js'
24+
25+
export interface WeixinServerDeps {
26+
enableConfigs(): void
27+
initializeAnalyticsSink(): void
28+
shutdownDatadog(): Promise<void>
29+
shutdown1PEventLogging(): Promise<void>
30+
logForDebugging(message: string): void
31+
registerPermissionHandler(
32+
server: Server,
33+
handler: (request: ChannelPermissionRequestParams) => Promise<void>,
34+
): void
35+
}
3236

3337
function formatPermissionRequestMessage(
3438
request: ChannelPermissionRequestParams,
@@ -45,9 +49,9 @@ function formatPermissionRequestMessage(
4549
].join('\n')
4650
}
4751

48-
export function createWeixinMcpServer(): Server {
52+
export function createWeixinMcpServer(version: string): Server {
4953
const server = new Server(
50-
{ name: 'weixin', version: MACRO.VERSION },
54+
{ name: 'weixin', version },
5155
{
5256
capabilities: {
5357
experimental: {
@@ -224,61 +228,60 @@ export function createWeixinMcpServer(): Server {
224228
return server
225229
}
226230

227-
export async function runWeixinMcpServer(): Promise<void> {
228-
enableConfigs()
229-
initializeAnalyticsSink()
231+
export async function runWeixinMcpServer(
232+
version: string,
233+
deps: WeixinServerDeps,
234+
): Promise<void> {
235+
deps.enableConfigs()
236+
deps.initializeAnalyticsSink()
230237

231238
const account = loadAccount()
232239
if (!account) {
233240
process.stderr.write(
234241
'[weixin] No account configured. Run `ccb weixin login` to connect your WeChat account.\n',
235242
)
236-
await Promise.all([shutdown1PEventLogging(), shutdownDatadog()])
243+
await Promise.all([deps.shutdown1PEventLogging(), deps.shutdownDatadog()])
237244
process.exit(1)
238245
}
239246

240-
const server = createWeixinMcpServer()
247+
const server = createWeixinMcpServer(version)
241248
const transport = new StdioServerTransport()
242249

243-
server.setNotificationHandler(
244-
ChannelPermissionRequestNotificationSchema(),
245-
async notification => {
246-
const request = notification.params
247-
const targetChatId = request.channel_context?.chat_id
248-
const targetChat = targetChatId
249-
? {
250-
chatId: targetChatId,
251-
contextToken: getContextToken(targetChatId),
252-
}
253-
: getActivePermissionChat()
250+
deps.registerPermissionHandler(server, async request => {
251+
const targetChatId = request.channel_context?.chat_id
252+
const targetChat = targetChatId
253+
? {
254+
chatId: targetChatId,
255+
contextToken: getContextToken(targetChatId),
256+
}
257+
: getActivePermissionChat()
254258

255-
if (!targetChat) {
256-
logForDebugging(
257-
`[Weixin MCP] No active chat available for permission request ${request.request_id}`,
258-
)
259-
return
260-
}
259+
if (!targetChat) {
260+
deps.logForDebugging(
261+
`[Weixin MCP] No active chat available for permission request ${request.request_id}`,
262+
)
263+
return
264+
}
261265

262-
try {
263-
savePendingPermission(
264-
request,
265-
targetChat.chatId,
266-
targetChat.contextToken,
267-
)
268-
await sendText({
269-
to: targetChat.chatId,
270-
text: formatPermissionRequestMessage(request),
271-
baseUrl,
272-
token: account.token,
273-
contextToken: targetChat.contextToken || '',
274-
})
275-
} catch (error) {
276-
process.stderr.write(
277-
`[weixin] Failed to relay permission request ${request.request_id}: ${error}\n`,
278-
)
279-
}
280-
},
281-
)
266+
try {
267+
savePendingPermission(
268+
request,
269+
targetChat.chatId,
270+
targetChat.contextToken,
271+
)
272+
await sendText({
273+
to: targetChat.chatId,
274+
text: formatPermissionRequestMessage(request),
275+
baseUrl,
276+
token: account.token,
277+
contextToken: targetChat.contextToken || '',
278+
})
279+
} catch (error) {
280+
process.stderr.write(
281+
`[weixin] Failed to relay permission request ${request.request_id}: ${error}\n`,
282+
)
283+
}
284+
})
282285

283286
await server.connect(transport)
284287

@@ -292,7 +295,7 @@ export async function runWeixinMcpServer(): Promise<void> {
292295
if (!controller.signal.aborted) {
293296
controller.abort()
294297
}
295-
await Promise.all([shutdown1PEventLogging(), shutdownDatadog()])
298+
await Promise.all([deps.shutdown1PEventLogging(), deps.shutdownDatadog()])
296299
process.exit(0)
297300
}
298301

@@ -313,7 +316,7 @@ export async function runWeixinMcpServer(): Promise<void> {
313316
}
314317
}, 5000)
315318

316-
logForDebugging('[Weixin MCP] Starting poll loop')
319+
deps.logForDebugging('[Weixin MCP] Starting poll loop')
317320
await startPollLoop({
318321
baseUrl,
319322
cdnBaseUrl: CDN_BASE_URL,

src/entrypoints/cli.tsx

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,25 @@ async function main(): Promise<void> {
143143
if (args[0] === 'weixin') {
144144
profileCheckpoint('cli_weixin_path')
145145
const { handleWeixinCli } = await import('@claude-code-best/weixin')
146-
const { runWeixinMcpServer } = await import('../services/weixin/cli-serve.js')
147-
await handleWeixinCli(args.slice(1), runWeixinMcpServer)
146+
const { enableConfigs } = await import('../utils/config.js')
147+
const { initializeAnalyticsSink } = await import('../services/analytics/sink.js')
148+
const { shutdownDatadog } = await import('../services/analytics/datadog.js')
149+
const { shutdown1PEventLogging } = await import('../services/analytics/firstPartyEventLogger.js')
150+
const { logForDebugging } = await import('../utils/debug.js')
151+
const { ChannelPermissionRequestNotificationSchema } = await import('../services/mcp/channelNotification.js')
152+
await handleWeixinCli(args.slice(1), {
153+
enableConfigs,
154+
initializeAnalyticsSink,
155+
shutdownDatadog,
156+
shutdown1PEventLogging,
157+
logForDebugging,
158+
registerPermissionHandler(server, handler) {
159+
server.setNotificationHandler(
160+
ChannelPermissionRequestNotificationSchema(),
161+
async notification => handler(notification.params),
162+
)
163+
},
164+
}, MACRO.VERSION)
148165
return
149166
}
150167

src/services/weixin/cli-serve.ts

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)