Files
oh-my-opencode/src/openclaw/AGENTS.md
T
YeonGyu-Kim 838b5ae216 docs(agents): refresh hierarchical AGENTS.md with team-mode coverage
Update root + 43 directory-level AGENTS.md files to reflect current state:
- Root AGENTS.md rewritten with accurate counts (1967 TS files, 1304 source +
  663 test, 278k LOC, 120 barrel index.ts), 7-step init flow, 5-tier hook
  composition, and full Team Mode section (12 team_* tools, eligibility,
  storage layout, config gate)
- src/AGENTS.md adds team-mode init step, current per-subdir file/LOC table
- src/tools/AGENTS.md documents conditional gates (team-mode +12, task
  system +4, hashline +1, interactive_bash +1, look_at +1) with always-on
  baseline of 20
- src/hooks/AGENTS.md splits into 5 tiers + 4 conditional team-mode hooks
- src/features/team-mode/AGENTS.md surfaces 12 tools, eligible agents,
  spawn-race-safe invariants, and integration points
- src/features/builtin-skills/AGENTS.md tracks 10 skills incl. team-mode
- src/agents/AGENTS.md, src/plugin/AGENTS.md, src/config/AGENTS.md updated
  for team-mode awareness, accurate counts, and current schema field list
- All other AGENTS.md files refreshed to 2026-05-08 generation date
2026-05-08 12:08:42 +09:00

3.6 KiB

src/openclaw/ — Bidirectional External Integration

Generated: 2026-05-08

OVERVIEW

18 files. Bidirectional integration system: outbound session event notifications (Discord/Telegram/HTTP webhook/shell command) AND inbound reply handling (daemon polls chat apps, injects replies back into tmux session). Named "claw" because it reaches out from OpenCode and pulls replies back in.

BIDIRECTIONAL FLOW

Outbound (OpenCode → External)

OpenCode session event → dispatchOpenClawEvent()
  → runtime-dispatch.ts: map event to OpenClaw event
  → dispatcher.ts: execute gateway (HTTP POST or shell command)
  → session-registry.ts: record message ID ↔ sessionID ↔ tmux pane

Inbound (External → OpenCode)

Discord/Telegram API → reply-listener daemon (separate Bun process)
  → reply-listener-{discord,telegram}.ts: poll every 3s
  → session-registry.ts: look up target tmux session from message ID
  → reply-listener-injection.ts: send-keys into tmux pane (rate limited)

KEY FILES

File Purpose
index.ts wakeOpenClaw(), initializeOpenClaw() — main entry
types.ts OpenClawConfig, OpenClawPayload, WakeResult types
config.ts Gateway resolution + URL validation (HTTPS required, localhost exception)
dispatcher.ts HTTP POST + shell command execution with variable interpolation
runtime-dispatch.ts Maps OpenCode events → OpenClaw events, orchestrates dispatch
session-registry.ts JSONL registry correlating message IDs ↔ sessions ↔ panes (file-locked)
reply-listener.ts Daemon lifecycle: start/stop, poll loop, state persistence
reply-listener-discord.ts Discord API polling
reply-listener-telegram.ts Telegram API polling
reply-listener-injection.ts Inject received reply into tmux pane (rate limiting + user filtering)
reply-listener-state.ts Daemon state: PID, config signature, poll tracking
daemon.ts Daemon entry point (runs as detached Bun process)
tmux.ts capturePane(), sendToPane() utilities

GATEWAY TYPES

Type Config Execution
HTTP webhook url field POST with JSON payload
Shell command command field Execute with env vars (OPENCLAW_*)

PAYLOAD VARIABLES (interpolation)

{sessionId}, {projectPath}, {tmuxSession}, {timestamp}, {eventType} (session.created/deleted/idle), {messageContent}, {promptSummary}

INTEGRATION POINTS

  • src/index.ts — calls initializeOpenClaw(pluginConfig.openclaw) at plugin startup (if enabled)
  • src/plugin/event.ts — calls dispatchOpenClawEvent() for session.created/deleted/idle
  • src/config/schema/openclaw.ts — Zod config schema

DAEMON LIFECYCLE

initializeOpenClaw(config)
  → wakeOpenClaw() if reply_listener.enabled
  → spawn daemon.ts as detached process
  → daemon writes PID to .opencode/openclaw.state.json
  → daemon polls Discord/Telegram every 3s
  → on reply: lookup in session-registry → inject into tmux via send-keys

SECURITY

  • URL validation: HTTPS required except localhost (config.ts)
  • Authorized users: Inbound replies filtered by allowed user ID list
  • Token redaction: Secrets masked in logs and error messages
  • Rate limiting: Reply injection throttled per pane

TESTING NOTE

reply-listener-discord.test.ts is always isolated in CI (listed in ALWAYS_ISOLATED_TEST_FILES of script/run-ci-tests.ts). Reason: mocks globalThis.fetch for Discord API simulation — needs process isolation to avoid interference with shared test batch.