mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-17 13:13:35 +08:00
DingTalk can receive interactive card callbacks, but the card UI still depends on a published template, so the adapter now supports a template-backed card path with text commands as the reliable fallback. Telegram and WeChat use the same allow-once, allow-always, and deny semantics so manual authorization behaves the same across platforms. Constraint: DingTalk button rendering requires an operator-provided interactive card template id Rejected: Treat the existing AI streaming card template as a permission card | it cannot guarantee visible action buttons Confidence: high Scope-risk: moderate Directive: Do not remove the text approval fallback unless DingTalk card template provisioning is guaranteed Tested: bun test adapters/common/__tests__/permission.test.ts adapters/dingtalk/__tests__/permission-card.test.ts adapters/telegram/__tests__/telegram.test.ts adapters/common/__tests__/config.test.ts src/server/__tests__/adapters.test.ts Tested: bunx tsc -p adapters/tsconfig.json --noEmit Tested: bun run check:adapters Tested: cd desktop && bun run build Tested: bun run check:server Tested: bun run check:docs Tested: git diff --check Not-tested: bun run quality:pr is blocked by existing CLI core approval policy; see artifacts/quality-runs/2026-05-03T13-19-56-232Z/report.md
30 lines
1.5 KiB
TypeScript
30 lines
1.5 KiB
TypeScript
import { describe, expect, it } from 'bun:test'
|
|
import {
|
|
formatPermissionDecisionStatus,
|
|
formatPermissionInstructions,
|
|
parsePermissionCommand,
|
|
parsePermitCallbackData,
|
|
} from '../permission.js'
|
|
|
|
describe('permission helpers', () => {
|
|
it('parses text permission commands', () => {
|
|
expect(parsePermissionCommand('/allow req-1')).toEqual({ requestId: 'req-1', allowed: true })
|
|
expect(parsePermissionCommand('/always req-2')).toEqual({ requestId: 'req-2', allowed: true, rule: 'always' })
|
|
expect(parsePermissionCommand('/allow-always req-3')).toEqual({ requestId: 'req-3', allowed: true, rule: 'always' })
|
|
expect(parsePermissionCommand('/deny req-4')).toEqual({ requestId: 'req-4', allowed: false })
|
|
})
|
|
|
|
it('parses callback permission actions', () => {
|
|
expect(parsePermitCallbackData('permit:req-1:yes')).toEqual({ requestId: 'req-1', allowed: true })
|
|
expect(parsePermitCallbackData('permit:req-2:always')).toEqual({ requestId: 'req-2', allowed: true, rule: 'always' })
|
|
expect(parsePermitCallbackData('permit:req-3:no')).toEqual({ requestId: 'req-3', allowed: false })
|
|
expect(parsePermitCallbackData('permit:req-4:unknown')).toBeNull()
|
|
})
|
|
|
|
it('formats text fallback and status labels', () => {
|
|
expect(formatPermissionInstructions('req-1')).toContain('/always req-1')
|
|
expect(formatPermissionDecisionStatus({ allowed: true, rule: 'always' })).toContain('永久允许')
|
|
expect(formatPermissionDecisionStatus({ allowed: false })).toContain('拒绝')
|
|
})
|
|
})
|