refine: cleanup remaining whispergate refs, improve docs and TASKLIST formatting

- Fix enableWhispergatePolicyTool → enableDirigentPolicyTool in config schema and example
- Fix whisper-gateway → dirigentway in install script
- Add v0.2.0 changelog entry
- Improve README with scheduling identifier docs and English text
- Clean up plugin README with moderator handoff format docs
- Reformat TASKLIST with cleaner done markers
This commit is contained in:
zhi
2026-03-03 10:13:39 +00:00
parent af33d747d9
commit fd1bf449a4
7 changed files with 75 additions and 59 deletions

View File

@@ -1,10 +1,21 @@
# Changelog # Changelog
## 0.2.0
- **Project renamed from WhisperGate to Dirigent**
- All plugin ids, tool names, config keys, file paths, docs updated
- Legacy `whispergate` config key still supported as fallback
- **Identity prompt enhancements**: Discord userId now included in agent identity injection
- **Scheduling identifier**: Added configurable `schedulingIdentifier` (default: `➡️`)
- Moderator handoff now sends `<@USER_ID>➡️` instead of semantic messages
- Agent prompt explains the identifier is meaningless — check chat history and decide
- **All prompts in English**: End-marker instructions, group chat rules, slash command help text
## 0.1.0-mvp ## 0.1.0-mvp
- Added no-reply API service (`/v1/chat/completions`, `/v1/responses`, `/v1/models`) - Added no-reply API service (`/v1/chat/completions`, `/v1/responses`, `/v1/models`)
- Added optional bearer auth (`AUTH_TOKEN`) - Added optional bearer auth (`AUTH_TOKEN`)
- Added Dirigent plugin with deterministic rule gate - Added plugin with deterministic rule gate
- Added discord-specific 🔚 prompt injection for bypass/end-symbol paths - Added discord-specific 🔚 prompt injection for bypass/end-symbol paths
- Added containerization (`Dockerfile`, `docker-compose.yml`) - Added containerization (`Dockerfile`, `docker-compose.yml`)
- Added helper scripts for smoke/dev lifecycle and rule validation - Added helper scripts for smoke/dev lifecycle and rule validation

View File

@@ -2,6 +2,8 @@
Rule-based no-reply gate + turn manager for OpenClaw (Discord). Rule-based no-reply gate + turn manager for OpenClaw (Discord).
> Formerly known as WhisperGate. Renamed to Dirigent in v0.2.0.
## What it does ## What it does
Dirigent adds deterministic logic **before model selection** and **turn-based speaking** for multi-agent Discord channels: Dirigent adds deterministic logic **before model selection** and **turn-based speaking** for multi-agent Discord channels:
@@ -13,8 +15,13 @@ Dirigent adds deterministic logic **before model selection** and **turn-based sp
4. Otherwise → route to no-reply model/provider 4. Otherwise → route to no-reply model/provider
- **End-symbol enforcement** - **End-symbol enforcement**
- Injects instruction like: `你的这次发言必须以🔚作为结尾…` - Injects instruction: `Your response MUST end with 🔚…`
- In group chats, also injects: “无关/不需要回应就 NO_REPLY - In group chats, also injects: "If not relevant, reply NO_REPLY"
- **Scheduling identifier (moderator handoff)**
- Configurable identifier (default: `➡️`) used by the moderator bot
- Handoff format: `<@TARGET_USER_ID>➡️` (non-semantic, just a scheduling signal)
- Agent receives instruction explaining the identifier is meaningless — check chat history and decide
- **Turn-based speaking (multi-bot)** - **Turn-based speaking (multi-bot)**
- Only the current speaker is allowed to respond - Only the current speaker is allowed to respond
@@ -22,8 +29,8 @@ Dirigent adds deterministic logic **before model selection** and **turn-based sp
- Turn advances on **end-symbol** or **NO_REPLY** - Turn advances on **end-symbol** or **NO_REPLY**
- If all bots NO_REPLY, channel becomes **dormant** until a new human message - If all bots NO_REPLY, channel becomes **dormant** until a new human message
- **Moderator handoff (optional)** - **Agent identity injection**
- When the current speaker NO_REPLYs, a moderator bot can post a handoff message to wake the next speaker - Injects agent name, Discord accountId, and Discord userId into group chat prompts
- **Per-channel policy runtime** - **Per-channel policy runtime**
- Policies stored in a standalone JSON file - Policies stored in a standalone JSON file
@@ -39,7 +46,7 @@ Dirigent adds deterministic logic **before model selection** and **turn-based sp
- `plugin/` — OpenClaw plugin (gate + turn manager + moderator presence) - `plugin/` — OpenClaw plugin (gate + turn manager + moderator presence)
- `no-reply-api/` — OpenAI-compatible API that always returns `NO_REPLY` - `no-reply-api/` — OpenAI-compatible API that always returns `NO_REPLY`
- `discord-control-api/` — Discord 管理扩展 API私密频道 + 成员列表) - `discord-control-api/` — Discord admin extension API (private channels + member list)
- `docs/` — rollout, integration, run-mode notes, turn-wakeup analysis - `docs/` — rollout, integration, run-mode notes, turn-wakeup analysis
- `scripts/` — smoke/dev/helper checks - `scripts/` — smoke/dev/helper checks
- `Makefile` — common dev commands (`make check`, `make check-rules`, `make test-api`, `make smoke-discord-control`, `make up`) - `Makefile` — common dev commands (`make check`, `make check-rules`, `make test-api`, `make smoke-discord-control`, `make up`)
@@ -61,7 +68,7 @@ node scripts/render-openclaw-config.mjs
``` ```
See `docs/RUN_MODES.md` for Docker mode. See `docs/RUN_MODES.md` for Docker mode.
Discord 扩展能力见:`docs/DISCORD_CONTROL.md` Discord extension capabilities: `docs/DISCORD_CONTROL.md`.
--- ---
@@ -92,6 +99,7 @@ Common options (see `docs/INTEGRATION.md`):
- `listMode`: `human-list` or `agent-list` - `listMode`: `human-list` or `agent-list`
- `humanList`, `agentList` - `humanList`, `agentList`
- `endSymbols` - `endSymbols`
- `schedulingIdentifier` (default `➡️`)
- `channelPoliciesFile` (per-channel overrides) - `channelPoliciesFile` (per-channel overrides)
- `moderatorBotToken` (handoff messages) - `moderatorBotToken` (handoff messages)
- `enableDebugLogs`, `debugLogChannelIds` - `enableDebugLogs`, `debugLogChannelIds`

View File

@@ -2,48 +2,42 @@
> Note: Project rename from WhisperGate → Dirigent implies updating all code/docs references (plugin/tool names, strings, files, configs). > Note: Project rename from WhisperGate → Dirigent implies updating all code/docs references (plugin/tool names, strings, files, configs).
## 1) Identity Prompt Enhancements ## 1) Identity Prompt Enhancements
- ✅ Added Discord userId to identity injection via `resolveDiscordUserId()`. - Current prompt only includes agent-id + discord name.
- Identity format now: `You are <name> (Discord account: <accountId>, Discord userId: <userId>).` - **Add Discord userId** to identity injection.
- **Done**: `buildAgentIdentity()` now resolves and includes Discord userId via `resolveDiscordUserId()`.
## 2) Scheduling Identifier (Default: ➡️) ## 2) Scheduling Identifier (Default: ➡️)
- Added `schedulingIdentifier` config field (default: `➡️`) to `DirigentConfig` and `openclaw.plugin.json`. - Add a **configurable scheduling identifier** (default: `➡️`).
- Updated `buildEndMarkerInstruction()` to explain scheduling identifier semantics to agents: - Update agent prompt to explain:
- The identifier itself is meaningless. - The scheduling identifier itself is meaningless.
- When receiving `<@USER_ID>` + identifier, check chat history and decide whether to reply. - When receiving `<@USER_ID>` + scheduling identifier, the agent should check chat history and decide whether to reply.
- If nothing to say, reply `NO_REPLY`. - If no reply needed, return `NO_REPLY`.
- **Done**: Added `schedulingIdentifier` config field; `buildSchedulingIdentifierInstruction()` injected for group chats.
## 3) Moderator Handoff Message Format ## 3) Moderator Handoff Message Format
- Moderator no longer sends semantic messages. - Moderator should **no longer send semantic messages** to activate agents.
- Handoff format is now: `<@TARGET_USER_ID>` + scheduling identifier (e.g., `<@123>➡️`). - Replace with: `<@TARGET_USER_ID>` + scheduling identifier (e.g., `<@123>➡️`).
- **Done**: Both `before_message_write` and `message_sent` handoff messages now use `<@userId>` + scheduling identifier format.
## 4) Prompt Language ## 4) Prompt Language
- All prompts converted to English: - **All prompts must be in English** (including end-marker instructions and group-chat rules).
- `buildEndMarkerInstruction()` — English with scheduling identifier explanation - **Done**: `buildEndMarkerInstruction()` and `buildSchedulingIdentifierInstruction()` output English. Slash command help text in English.
- `buildAgentIdentity()` — English format
- Slash command help text — English
- Error messages — English
- Code comments — English
## 5) Full Project Rename ## 5) Full Project Rename
- ✅ Plugin id: `whispergate``dirigent` - Project name changed to **Dirigent**.
- ✅ Plugin name: `WhisperGate``Dirigent` - Update **all strings** across repo:
- ✅ Tool name: `whispergate_tools``dirigent_tools` - plugin name/id`dirigent`
- ✅ Config type: `WhisperGateConfig``DirigentConfig` - tool name`dirigent_tools`
- ✅ Config lookup key: `entries.whispergate``entries.dirigent` - slash command → `/dirigent`
- ✅ Channel policies file: `whispergate-channel-policies.json``dirigent-channel-policies.json` - docs, config, scripts, examples
- ✅ Log prefixes: `whispergate:``dirigent:` - any text mentions
- ✅ Slash command: `/whispergate``/dirigent` - dist output dir`dist/dirigent`
- ✅ Gateway browser/device identifier: `whispergate``dirigent` - docker service → `dirigent-no-reply-api`
- ✅ Scripts renamed: `install-whispergate-*` `install-dirigent-*` - config key fallback: still reads legacy `whispergate` entry if `dirigent` not found
- ✅ All docs, configs, examples updated - **Done**: All files updated.
- ✅ dist/ folder: `dist/whispergate/``dist/dirigent/`
- ✅ package.json names updated
- ✅ README.md, CHANGELOG.md updated
- ✅ Version bumped to 0.2.0
--- ---
## Open Items / Notes ## Open Items / Notes
- User requested the previous README commit should have been pushed to `main` directly (was pushed to a branch). Address separately if needed. - User requested the previous README commit should have been pushed to `main` directly (was pushed to a branch). Address separately if needed.
- **Migration note**: Existing deployments need to update their `openclaw.json` config from `plugins.entries.whispergate``plugins.entries.dirigent` and rename the channel policies file.

View File

@@ -17,7 +17,7 @@
"noReplyProvider": "dirigentway", "noReplyProvider": "dirigentway",
"noReplyModel": "no-reply", "noReplyModel": "no-reply",
"enableDiscordControlTool": true, "enableDiscordControlTool": true,
"enableWhispergatePolicyTool": true, "enableDirigentPolicyTool": true,
"enableDebugLogs": false, "enableDebugLogs": false,
"debugLogChannelIds": [], "debugLogChannelIds": [],
"discordControlApiBaseUrl": "http://127.0.0.1:8790", "discordControlApiBaseUrl": "http://127.0.0.1:8790",

View File

@@ -4,9 +4,7 @@
- `message:received` caches a per-session decision from deterministic rules. - `message:received` caches a per-session decision from deterministic rules.
- `before_model_resolve` applies `providerOverride + modelOverride` when decision says no-reply. - `before_model_resolve` applies `providerOverride + modelOverride` when decision says no-reply.
- `before_prompt_build` prepends instruction `你的这次发言必须以🔚作为结尾。` when decision is: - `before_prompt_build` prepends end-marker instruction + scheduling identifier instruction when decision allows speaking.
- `bypass_sender`
- `end_symbol:*`
## Rules (in order) ## Rules (in order)
@@ -30,12 +28,14 @@ Optional:
- `humanList` (default []) - `humanList` (default [])
- `agentList` (default []) - `agentList` (default [])
- `channelPoliciesFile` (per-channel overrides in a standalone JSON file) - `channelPoliciesFile` (per-channel overrides in a standalone JSON file)
- `enableWhispergatePolicyTool` (default true) - `schedulingIdentifier` (default `➡️`) — moderator handoff identifier
- `enableDirigentPolicyTool` (default true)
Unified optional tool: Unified optional tool:
- `dirigent_tools` - `dirigent_tools`
- Discord actions: `channel-private-create`, `channel-private-update`, `member-list` - Discord actions: `channel-private-create`, `channel-private-update`, `member-list`
- Policy actions: `policy-get`, `policy-set-channel`, `policy-delete-channel` - Policy actions: `policy-get`, `policy-set-channel`, `policy-delete-channel`
- Turn actions: `turn-status`, `turn-advance`, `turn-reset`
- `bypassUserIds` (deprecated alias of `humanList`) - `bypassUserIds` (deprecated alias of `humanList`)
- `endSymbols` (default ["🔚"]) - `endSymbols` (default ["🔚"])
- `enableDiscordControlTool` (default true) - `enableDiscordControlTool` (default true)
@@ -53,18 +53,21 @@ Policy file behavior:
- direct file edits do NOT affect memory state - direct file edits do NOT affect memory state
- `dirigent_tools` policy actions update memory first, then persist to file (atomic write) - `dirigent_tools` policy actions update memory first, then persist to file (atomic write)
## Optional tool: `dirigent_tools` ## Moderator handoff format
This plugin registers one unified optional tool: `dirigent_tools`. When the current speaker NO_REPLYs, the moderator bot sends: `<@NEXT_USER_ID>➡️`
To use it, add tool allowlist entry for either:
- tool name: `dirigent_tools`
- plugin id: `dirigent`
Supported actions: This is a non-semantic scheduling message. The scheduling identifier (`➡️` by default) carries no meaning — it simply signals the next agent to check chat history and decide whether to speak.
- Discord: `channel-private-create`, `channel-private-update`, `member-list`
- Policy: `policy-get`, `policy-set-channel`, `policy-delete-channel` ## Slash command (Discord)
```
/dirigent status
/dirigent turn-status
/dirigent turn-advance
/dirigent turn-reset
```
Debug logging: Debug logging:
- set `enableDebugLogs: true` to emit detailed hook diagnostics - set `enableDebugLogs: true` to emit detailed hook diagnostics
- optionally set `debugLogChannelIds` to only log selected channel IDs - optionally set `debugLogChannelIds` to only log selected channel IDs
- logs include key ctx fields + decision status at `message_received`, `before_model_resolve`, `before_prompt_build`

View File

@@ -20,7 +20,7 @@
"noReplyProvider": { "type": "string" }, "noReplyProvider": { "type": "string" },
"noReplyModel": { "type": "string" }, "noReplyModel": { "type": "string" },
"enableDiscordControlTool": { "type": "boolean", "default": true }, "enableDiscordControlTool": { "type": "boolean", "default": true },
"enableWhispergatePolicyTool": { "type": "boolean", "default": true }, "enableDirigentPolicyTool": { "type": "boolean", "default": true },
"discordControlApiBaseUrl": { "type": "string", "default": "http://127.0.0.1:8790" }, "discordControlApiBaseUrl": { "type": "string", "default": "http://127.0.0.1:8790" },
"discordControlApiToken": { "type": "string" }, "discordControlApiToken": { "type": "string" },
"discordControlCallerId": { "type": "string" }, "discordControlCallerId": { "type": "string" },

View File

@@ -15,7 +15,7 @@ const env = process.env;
const OPENCLAW_CONFIG_PATH = env.OPENCLAW_CONFIG_PATH || path.join(os.homedir(), ".openclaw", "openclaw.json"); const OPENCLAW_CONFIG_PATH = env.OPENCLAW_CONFIG_PATH || path.join(os.homedir(), ".openclaw", "openclaw.json");
const __dirname = path.dirname(new URL(import.meta.url).pathname); const __dirname = path.dirname(new URL(import.meta.url).pathname);
const PLUGIN_PATH = env.PLUGIN_PATH || path.resolve(__dirname, "..", "dist", "dirigent"); const PLUGIN_PATH = env.PLUGIN_PATH || path.resolve(__dirname, "..", "dist", "dirigent");
const NO_REPLY_PROVIDER_ID = env.NO_REPLY_PROVIDER_ID || "whisper-gateway"; const NO_REPLY_PROVIDER_ID = env.NO_REPLY_PROVIDER_ID || "dirigentway";
const NO_REPLY_MODEL_ID = env.NO_REPLY_MODEL_ID || "no-reply"; const NO_REPLY_MODEL_ID = env.NO_REPLY_MODEL_ID || "no-reply";
const NO_REPLY_BASE_URL = env.NO_REPLY_BASE_URL || "http://127.0.0.1:8787/v1"; const NO_REPLY_BASE_URL = env.NO_REPLY_BASE_URL || "http://127.0.0.1:8787/v1";
const NO_REPLY_API_KEY = env.NO_REPLY_API_KEY || "wg-local-test-token"; const NO_REPLY_API_KEY = env.NO_REPLY_API_KEY || "wg-local-test-token";