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:
13
CHANGELOG.md
13
CHANGELOG.md
@@ -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
|
||||||
|
|||||||
20
README.md
20
README.md
@@ -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`
|
||||||
|
|||||||
66
TASKLIST.md
66
TASKLIST.md
@@ -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.
|
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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`
|
|
||||||
|
|||||||
@@ -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" },
|
||||||
|
|||||||
@@ -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";
|
||||||
|
|||||||
Reference in New Issue
Block a user