docs: reorganize planning and archive files
This commit is contained in:
158
achieve/FEAT.md
Normal file
158
achieve/FEAT.md
Normal file
@@ -0,0 +1,158 @@
|
||||
# Dirigent — Feature List
|
||||
|
||||
All implemented features across all versions.
|
||||
|
||||
---
|
||||
|
||||
## Core: Rule-Based No-Reply Gate
|
||||
- Deterministic logic in `before_model_resolve` hook decides whether to route to no-reply model
|
||||
- **human-list** mode: humanList senders bypass gate; others need end symbol to pass
|
||||
- **agent-list** mode: agentList senders need end symbol; others bypass
|
||||
- Non-Discord messages skip entirely
|
||||
- DM sessions (no metadata) always bypass
|
||||
- Per-channel policy overrides via JSON file (runtime-updateable)
|
||||
|
||||
## Core: End-Symbol Enforcement
|
||||
- Injects prompt instruction: "Your response MUST end with 🔚"
|
||||
- Gateway keywords (NO_REPLY, HEARTBEAT_OK) exempt from end symbol
|
||||
- Group chats get additional rule: "If not relevant, reply NO_REPLY"
|
||||
- End symbols configurable per-channel via policy
|
||||
|
||||
## Core: No-Reply API
|
||||
- OpenAI-compatible API (`/v1/chat/completions`, `/v1/responses`, `/v1/models`)
|
||||
- Always returns `NO_REPLY` — used as the override model target
|
||||
- Optional bearer auth (`AUTH_TOKEN`)
|
||||
- Auto-started/stopped with gateway lifecycle
|
||||
|
||||
## Turn-Based Speaking (Multi-Bot)
|
||||
- Only the current speaker is allowed to respond; others forced to no-reply model
|
||||
- Turn order auto-populated from bot accounts seen in each channel
|
||||
- Turn advances on end-symbol (successful speech) or NO_REPLY
|
||||
- Successful speech resets NO_REPLY cycle counter
|
||||
- If all bots NO_REPLY in a cycle → channel goes **dormant**
|
||||
- Dormant reactivation: human message → first in order; bot message → next after sender
|
||||
- Turn timeout: auto-advance after 60s of inactivity
|
||||
- Manual control: `/dirigent turn-status`, `/dirigent turn-advance`, `/dirigent turn-reset`
|
||||
|
||||
## Human @Mention Override *(v0.3.0)*
|
||||
- When a `humanList` user @mentions specific agents (`<@USER_ID>`):
|
||||
- Extracts mentioned Discord user IDs from message content
|
||||
- Maps userIds → accountIds via reverse bot token lookup
|
||||
- Filters to agents in the current turn order
|
||||
- Orders by their position in the current turn order
|
||||
- Temporarily replaces speaking order with only those agents
|
||||
- Cycle: a → b → c → (back to a) → restore original order, go dormant
|
||||
- Edge cases:
|
||||
- All override agents NO_REPLY → restore + dormant
|
||||
- `resetTurn` clears any active override
|
||||
- Human message without mentions → restores override, normal flow
|
||||
- Mentioned users not in turn order → ignored
|
||||
|
||||
## Agent Identity Injection
|
||||
- Group chat prompts include: agent name, Discord accountId, Discord userId
|
||||
- userId resolved from bot token (base64 first segment)
|
||||
|
||||
## Wait for Human Reply *(v0.3.0)*
|
||||
- Configurable wait identifier (default: `👤`)
|
||||
- Agent ends message with `👤` instead of `🔚` when it needs a human to reply
|
||||
- Triggers "waiting for human" state:
|
||||
- All agents routed to no-reply model
|
||||
- Turn manager goes dormant
|
||||
- State clears automatically when a human sends a message
|
||||
- Prompt injection tells agents:
|
||||
- Use wait identifier only when confident the human is actively participating
|
||||
- Do NOT use it speculatively
|
||||
- Works with mention override: wait identifier during override also triggers waiting state
|
||||
|
||||
## Scheduling Identifier
|
||||
- Configurable identifier (default: `➡️`) used for moderator handoff
|
||||
- Handoff format: `<@TARGET_USER_ID>➡️` (non-semantic scheduling signal)
|
||||
- Agent prompt explains: identifier is meaningless — check chat history, decide whether to reply
|
||||
- If nothing to say → NO_REPLY
|
||||
|
||||
## Moderator Bot Presence
|
||||
- Maintains Discord Gateway WebSocket connection for moderator bot
|
||||
- Shows "online" status with "Moderating" activity
|
||||
- Handles reconnect, resume, heartbeat, invalid session recovery
|
||||
- Singleton guard prevents duplicate connections
|
||||
- Sends handoff messages to trigger next speaker's turn
|
||||
|
||||
## Individual Tools *(v0.3.0)*
|
||||
Six standalone tools (split from former monolithic `dirigent_tools`):
|
||||
|
||||
### Discord Control
|
||||
- **`dirigent_discord_channel_create`** — Create private Discord channel with user/role permissions
|
||||
- **`dirigent_discord_channel_update`** — Update permissions on existing private channel
|
||||
- **`dirigent_discord_member_list`** — List guild members with pagination and field projection
|
||||
|
||||
### Policy Management
|
||||
- **`dirigent_policy_get`** — Get all channel policies
|
||||
- **`dirigent_policy_set`** — Set/update a channel policy (listMode, humanList, agentList, endSymbols)
|
||||
- **`dirigent_policy_delete`** — Delete a channel policy
|
||||
|
||||
### Turn Management (internal only — not exposed as tools)
|
||||
Turn management is handled entirely by the plugin. Manual control via slash commands:
|
||||
- `/dirigent turn-status` — Show turn state
|
||||
- `/dirigent turn-advance` — Manually advance to next speaker
|
||||
- `/dirigent turn-reset` — Reset turn order (go dormant, clear overrides)
|
||||
|
||||
## Slash Command: `/dirigent`
|
||||
- `status` — Show all channel policies
|
||||
- `turn-status` — Show turn state for current channel
|
||||
- `turn-advance` — Manually advance turn
|
||||
- `turn-reset` — Reset turn order
|
||||
|
||||
## Project Rename (WhisperGate → Dirigent) *(v0.2.0)*
|
||||
- All plugin ids, tool names, config keys, file paths, docs updated
|
||||
- Legacy `whispergate` config key still supported as fallback
|
||||
|
||||
## Installer Script *(updated v0.3.0)*
|
||||
- `scripts/install-dirigent-openclaw.mjs`
|
||||
- `--install` / `--uninstall` / `--update` modes
|
||||
- **Dynamic OpenClaw dir resolution**: `$OPENCLAW_DIR` → `openclaw config get dataDir` → `~/.openclaw`
|
||||
- Builds dist and copies to `$(openclaw_dir)/plugins/dirigent`
|
||||
- `--update`: pulls latest from git `latest` branch, then reinstalls
|
||||
- Auto-reinstall (uninstall + install) if already installed
|
||||
- Backup before changes, rollback on failure
|
||||
- Records stored in `$(openclaw_dir)/dirigent-install-records/`
|
||||
|
||||
## Discord Control API (Sidecar)
|
||||
- Private channel create/update with permission overwrites
|
||||
- Member list with pagination + field projection
|
||||
- Guardrails: action validation, id-list limits, response-size limit
|
||||
- (Migrated) Discord control now runs in-plugin via direct Discord REST (no companion service)
|
||||
|
||||
---
|
||||
|
||||
## NEW_FEAT 合并记录(原 NEW_FEAT.md)
|
||||
|
||||
### 背景与目标
|
||||
- 解决 turn 初始化依赖被动观察(`recordChannelAccount`)导致 `currentSpeaker` 空值的问题。
|
||||
- 将 Discord control 从 sidecar 迁移到插件内模块。
|
||||
- 采用 channel 成员缓存(内存 + 本地持久化),避免轮询。
|
||||
|
||||
### 关键实现方向
|
||||
- 统一 channelId 解析链路,避免 `channel=discord` 错位。
|
||||
- `before_model_resolve / before_prompt_build` 与消息 hook 使用一致解析策略。
|
||||
- 清理未使用函数,降低排障噪音。
|
||||
- 模块化重构:`index.ts` 作为 wiring,逻辑拆入 `hooks/core/tools/policy/commands`。
|
||||
|
||||
### Channel 成员缓存
|
||||
- 缓存文件:`~/.openclaw/dirigent-channel-members.json`
|
||||
- 启动加载、运行时原子写盘。
|
||||
- 记录字段包含 `botAccountIds/updatedAt/source/guildId`。
|
||||
- 首次无缓存时允许 bootstrap 拉取,随后走本地缓存。
|
||||
|
||||
### Turn 初始化改造
|
||||
- `ensureTurnOrder(channelId)` 基于缓存中的 botAccountIds 初始化。
|
||||
- 不再仅依赖“已见账号”被动记录。
|
||||
- 提升新频道首条消息场景的稳定性。
|
||||
|
||||
### 权限计算(频道可见成员)
|
||||
- 通过 guild 成员 + roles + channel overwrites 计算 `VIEW_CHANNEL` 可见性。
|
||||
- 用于内部 turn bootstrap,不对外暴露为公共工具。
|
||||
|
||||
### 风险与注意
|
||||
- 权限位计算必须严格按 Discord 规则。
|
||||
- 缓存读写需原子化,防并发损坏。
|
||||
- 通过 `updatedAt/source/guildId` 提高可观测性与排障效率。
|
||||
Reference in New Issue
Block a user