Files
Dirigent/achieve/FEAT.md

7.3 KiB
Raw Permalink Blame History

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_DIRopenclaw 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 提高可观测性与排障效率。