Skip to content
Draft
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
87975ca
feat(qq-bot): add qq bot service
PhoenixForrestLin Apr 15, 2026
9efb7e5
fix(deps): 修复缺失的依赖
PhoenixForrestLin Apr 15, 2026
13a5fb3
[autofix.ci] apply automated fixes
autofix-ci[bot] Apr 15, 2026
ce8f220
fix(qq-bot): 修复 DecorateStage 长文本拆分失效
PhoenixForrestLin Apr 15, 2026
d23c8a7
fix(qq-bot): ProcessStage 并发安全 (correlationId)
PhoenixForrestLin Apr 15, 2026
1a760bf
fix(qq-bot): 清理 airi-client 重复注册与私有属性访问
PhoenixForrestLin Apr 15, 2026
d2e613e
fix(qq-bot): FilterStage 空消息过滤逻辑
PhoenixForrestLin Apr 15, 2026
e8759af
fix(qq-bot): RateLimitStage interval 泄漏
PhoenixForrestLin Apr 15, 2026
77f675c
refactor(qq-bot): PipelineExtensions 显式声明 proc_clearSession
PhoenixForrestLin Apr 15, 2026
d8e2a3d
refactor(qq-bot): AgentLoop 消除 any 类型
PhoenixForrestLin Apr 15, 2026
fbc6d69
build(qq-bot): Dockerfile 多阶段构建 + monorepo 支持
PhoenixForrestLin Apr 15, 2026
ef06dcc
chore(qq-bot): 固定 naplink 版本 + 更新文档
PhoenixForrestLin Apr 15, 2026
29f10bd
docs(qq-bot): 更新 README,明确 airi 链接需要 token
PhoenixForrestLin Apr 15, 2026
20bc27d
Merge branch 'feat/qq-bot' of github.com:PhoenixForrestLin/airi into …
PhoenixForrestLin Apr 15, 2026
896352b
fix(qq-bot): 订阅 poke 事件到生产入口
PhoenixForrestLin Apr 15, 2026
23348d0
fix(qq-bot): normalize AIRI structured content before trim && WakeSta…
PhoenixForrestLin Apr 15, 2026
e9b1586
fix(qq-bot): restrict reply wakeups to replies targeting the bot
PhoenixForrestLin Apr 16, 2026
5e723f5
fix(qq-bot): parse commands before enforcing wake-up gating
PhoenixForrestLin Apr 16, 2026
f11713c
fix(qq-bot): normalize summary output content before trimming
PhoenixForrestLin Apr 16, 2026
a497ba5
fix(qq-bot): prevent lost updates when persisting conversation history
PhoenixForrestLin Apr 16, 2026
a65646c
fix(qq-bot): advance checkpoint when proactive decision is wait
PhoenixForrestLin Apr 16, 2026
7a7d799
Merge branch 'moeru-ai:main' into feat/qq-bot
PhoenixForrestLin Apr 16, 2026
60e53a2
fix(qq-bot): always release conversation mutex in runner exit paths
PhoenixForrestLin Apr 16, 2026
5038ccf
fix(qq-bot): align NodeNext ESM runtime behavior
PhoenixForrestLin Apr 16, 2026
cdc2608
fix(qq-bot): add id tie-breaker to message-history ordering
PhoenixForrestLin Apr 16, 2026
5559a80
Merge branch 'moeru-ai:main' into feat/qq-bot
PhoenixForrestLin Apr 16, 2026
a684c5f
fix: 防止会话锁双重释放 & 补全 Dockerfile 拓扑构建
PhoenixForrestLin Apr 16, 2026
51d54ce
Merge branch 'main' into feat/qq-bot
PhoenixForrestLin Apr 16, 2026
f814f54
fix(qq-bot): 显式配置 botQQ 以修复 @bot 唤醒失效
PhoenixForrestLin Apr 16, 2026
b45651f
Merge branch 'moeru-ai:main' into feat/qq-bot
PhoenixForrestLin Apr 17, 2026
32628ff
[autofix.ci] apply automated fixes
autofix-ci[bot] Apr 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
395 changes: 353 additions & 42 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ catalog:
'@iconify-json/ph': ^1.2.2
'@iconify-json/tabler': ^1.2.33
'@intlify/core': ^11.3.2
'@libsql/client': ^0.15.15
'@modelcontextprotocol/sdk': ^1.29.0
'@moeru/eslint-config': 0.1.0-beta.15
'@moeru/eventa': 1.0.0-beta.3
Expand Down Expand Up @@ -97,6 +98,7 @@ catalog:
embla-carousel-vue: 9.0.0-rc02
es-toolkit: 1.43.0
get-port-please: ^3.2.0
gpt-tokenizer: ^3.4.0
histoire: 1.0.0-beta.1
hono: 4.11.3
hono-rate-limiter: ^0.5.3
Expand All @@ -116,6 +118,8 @@ catalog:
pinia: ^3.0.4
posthog-js: 1.306.1
splitpanes: ^4.0.4
sql.js: ^1.13.0
sqlite-vec: ^0.1.7-alpha.2
std-env: ^4.0.0
superjson: ^2.2.6
tsdown: ^0.21.8
Expand Down
Empty file added services/qq-bot/.env
Empty file.
65 changes: 65 additions & 0 deletions services/qq-bot/.github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Copilot instructions for `services/qq-bot`

## Build, test, and lint commands

Run commands from repo root (`airi`) unless noted.

- Install workspace deps: `pnpm install`
- Run this service once: `pnpm -F @proj-airi/qq-bot start`
- Run this service in watch mode: `pnpm -F @proj-airi/qq-bot dev`
- Typecheck this service: `pnpm -F @proj-airi/qq-bot typecheck`

Repository-level commands (used when validating broader impact):

- Lint all workspaces: `pnpm lint`
- Auto-fix lint/format: `pnpm lint:fix`
- Run all tests: `pnpm test:run`

Single test command pattern:

- `pnpm exec vitest run <path/to/test-file>`
- Example: `pnpm exec vitest run services/qq-bot/src/some-feature.test.ts`

## High-level architecture

This package is a QQ OneBot adapter scaffold built around NapLink and a staged message pipeline.

- `src/config.ts` is the configuration center:
- defines `BotConfigSchema` with Valibot,
- exports all config types via `v.InferOutput`,
- loads YAML and applies env fallback for LLM fields (`LLM_API_BASE_URL`, `LLM_API_KEY`, `LLM_MODEL`).
- `src/client.ts` is the runtime composition root:
- builds `NapLink` client,
- wires `Dispatcher -> PipelineRunner`,
- normalizes incoming `message.group` / `message.private` events,
- runs graceful shutdown (`SIGINT` / `SIGTERM`).
- `src/types/*` defines protocol-safe internal contracts:
- `event.ts`: normalized `QQMessageEvent` and `sessionId` format (`qq:{type}:{id}`),
- `context.ts`: pipeline blackboard (`PipelineContext`) and `StageResult`,
- `message.ts`: typed message segments with input/output separation,
- `response.ts`: discriminated union payloads + fail-fast factory helpers.
- `src/pipeline/stage.ts` defines the stage base contract and timing/error wrapper.
- `src/pipeline/extensions.ts` reserves a strongly-typed cross-stage extension area.
- `src/utils/logger.ts` + `src/utils/naplink-logger-adapter.ts` provide unified logging and NapLink logger bridging.

Design reference for the intended 7-stage pipeline (`Filter -> Wake -> RateLimit -> Session -> Process -> Decorate -> Respond`) is in:

- `Project AIRI — QQ OneBot 适配器设计文档 ... .md`

Current repository status to keep in mind while coding:

- Treat the checked-in source tree as the source of truth.

## Key conventions in this codebase

- Keep config as a single source of truth in Valibot schemas; derive TS types from schemas instead of parallel interfaces.
- Use explicit discriminated unions (`kind`, `action`, `type`) for pipeline flow and payloads; avoid loosely typed records.
- Preserve the input/output message segment split:
- input may contain `reply` segments,
- output payloads must not contain `reply`; use `replyTo` and let dispatch layer inject reply segments.
- Use `PipelineContext` as the shared stage blackboard; cross-stage extra data belongs in `context.extensions` with typed fields, not ad-hoc metadata.
- Follow fail-fast helpers in `src/types/response.ts` (throw on invalid empty payloads) instead of silent fallbacks.
- Keep session identity format consistent: `qq:{sourceType}:{groupId|userId}`.
- Prefer factory-based assembly for runtime wiring (`createBot`, `createDispatcher`, normalizers, runner) and keep orchestration in composition roots.
- Route all logs through `createLogger(...)`/`initLoggers(...)`; do not introduce standalone logging patterns.
- Use `pnpm` workspace filters (`pnpm -F ...`) for service-scoped runs in this monorepo.
3 changes: 3 additions & 0 deletions services/qq-bot/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Ignore the config file and data directory
config.yaml
data/*
34 changes: 34 additions & 0 deletions services/qq-bot/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
FROM node:22-alpine AS builder

WORKDIR /app

RUN corepack enable

COPY pnpm-lock.yaml pnpm-workspace.yaml package.json tsconfig.json ./
COPY services/qq-bot/package.json services/qq-bot/tsconfig.json ./services/qq-bot/
COPY services/qq-bot/src ./services/qq-bot/src
COPY packages/server-sdk/package.json packages/server-sdk/tsconfig.json ./packages/server-sdk/
COPY packages/server-sdk/src ./packages/server-sdk/src
COPY packages/server-shared/package.json packages/server-shared/tsconfig.json ./packages/server-shared/
COPY packages/server-shared/src ./packages/server-shared/src

RUN pnpm install --frozen-lockfile
RUN pnpm --filter @proj-airi/qq-bot build
Comment thread
PhoenixForrestLin marked this conversation as resolved.
Outdated

FROM node:22-alpine AS production

WORKDIR /app

RUN corepack enable

COPY pnpm-lock.yaml pnpm-workspace.yaml package.json ./
COPY services/qq-bot/package.json ./services/qq-bot/package.json
COPY packages/server-sdk/package.json ./packages/server-sdk/package.json
COPY packages/server-sdk/src ./packages/server-sdk/src
COPY packages/server-shared/package.json ./packages/server-shared/package.json
COPY packages/server-shared/src ./packages/server-shared/src
COPY --from=builder /app/services/qq-bot/dist ./services/qq-bot/dist

RUN pnpm install --frozen-lockfile --prod

CMD ["node", "services/qq-bot/dist/index.js"]
Loading
Loading