mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-17 13:13:35 +08:00
WeChat needs a QR-paired path instead of bot-token setup, so the adapter layer now includes the iLink protocol calls, desktop pairing UI, server-side bind/unbind APIs, and shared IM command behavior. Empty project history falls back to the user's default work directory so mobile /new works without pre-opening a desktop project. Constraint: Tencent iLink login returns a URL that the desktop UI must render as a QR image locally Constraint: IM adapters should keep /new, /projects, status, permission, and default workdir behavior consistent across WeChat, Feishu, and Telegram Rejected: Require users to paste absolute project paths for first WeChat sessions | mobile onboarding should work from the default user working directory Confidence: high Scope-risk: moderate Directive: Do not change WeChat polling back to overlapping intervals; getupdates is a long-poll endpoint and must remain serialized Tested: Real WeChat QR scan, inbound /status, outbound reply, and unbind E2E Tested: bun run check:adapters Tested: bun run quality:pr Not-tested: Re-scan live WeChat after the default-workdir fallback tweak; covered by adapter config tests and PR gate
69 lines
2.6 KiB
TypeScript
69 lines
2.6 KiB
TypeScript
import { afterEach, describe, expect, it } from 'bun:test'
|
|
import * as fs from 'node:fs'
|
|
import * as os from 'node:os'
|
|
import * as path from 'node:path'
|
|
import { getConfiguredWorkDir, loadConfig } from '../config.js'
|
|
|
|
describe('adapter config defaults', () => {
|
|
const originalConfigDir = process.env.CLAUDE_CONFIG_DIR
|
|
const originalAdapterDefaultWorkDir = process.env.CLAUDE_ADAPTER_DEFAULT_WORK_DIR
|
|
const originalPwd = process.env.PWD
|
|
|
|
afterEach(() => {
|
|
restoreEnv('CLAUDE_CONFIG_DIR', originalConfigDir)
|
|
restoreEnv('CLAUDE_ADAPTER_DEFAULT_WORK_DIR', originalAdapterDefaultWorkDir)
|
|
restoreEnv('PWD', originalPwd)
|
|
})
|
|
|
|
it('uses the user shell working directory when no default project is configured', () => {
|
|
const configDir = fs.mkdtempSync(path.join(os.tmpdir(), 'adapter-config-'))
|
|
const workDir = fs.mkdtempSync(path.join(os.tmpdir(), 'adapter-workdir-'))
|
|
try {
|
|
process.env.CLAUDE_CONFIG_DIR = configDir
|
|
delete process.env.CLAUDE_ADAPTER_DEFAULT_WORK_DIR
|
|
process.env.PWD = workDir
|
|
|
|
const config = loadConfig()
|
|
|
|
expect(config.telegram.defaultWorkDir).toBe(fs.realpathSync(workDir))
|
|
expect(config.feishu.defaultWorkDir).toBe(fs.realpathSync(workDir))
|
|
expect(config.wechat.defaultWorkDir).toBe(fs.realpathSync(workDir))
|
|
expect(getConfiguredWorkDir(config, config.wechat)).toBe(fs.realpathSync(workDir))
|
|
} finally {
|
|
fs.rmSync(configDir, { recursive: true, force: true })
|
|
fs.rmSync(workDir, { recursive: true, force: true })
|
|
}
|
|
})
|
|
|
|
it('keeps the explicit default project ahead of the platform default work dir', () => {
|
|
const configDir = fs.mkdtempSync(path.join(os.tmpdir(), 'adapter-config-'))
|
|
const defaultProjectDir = fs.mkdtempSync(path.join(os.tmpdir(), 'adapter-project-'))
|
|
const workDir = fs.mkdtempSync(path.join(os.tmpdir(), 'adapter-workdir-'))
|
|
try {
|
|
fs.writeFileSync(
|
|
path.join(configDir, 'adapters.json'),
|
|
JSON.stringify({ defaultProjectDir }),
|
|
)
|
|
process.env.CLAUDE_CONFIG_DIR = configDir
|
|
process.env.CLAUDE_ADAPTER_DEFAULT_WORK_DIR = workDir
|
|
|
|
const config = loadConfig()
|
|
|
|
expect(getConfiguredWorkDir(config, config.wechat)).toBe(defaultProjectDir)
|
|
expect(config.wechat.defaultWorkDir).toBe(fs.realpathSync(workDir))
|
|
} finally {
|
|
fs.rmSync(configDir, { recursive: true, force: true })
|
|
fs.rmSync(defaultProjectDir, { recursive: true, force: true })
|
|
fs.rmSync(workDir, { recursive: true, force: true })
|
|
}
|
|
})
|
|
})
|
|
|
|
function restoreEnv(key: string, value: string | undefined): void {
|
|
if (value === undefined) {
|
|
delete process.env[key]
|
|
} else {
|
|
process.env[key] = value
|
|
}
|
|
}
|