forked from molecule-ai/molecule-core
Why this exists --------------- Live evidence on 2026-05-01 caught a regression latent in #46's "push-feel inbound" closure: standard `claude` launches without `--dangerously-load-development-channels` silently drop our `notifications/claude/channel` emissions, so canvas/peer messages sat in the wheel inbox and never reached the agent loop until manual `inbox_peek`. The flag is research-preview-only; non-Claude-Code MCP clients (Cursor, Cline, OpenCode, hermes-agent, codex) never receive the notification at all because the method namespace is Claude- specific. Push-only delivery shipped as the universal contract is not actually universal. What this changes ----------------- Adds a poll path that works on every spec-compliant MCP client. The `initialize` `instructions` field — read by every client and surfaced to the agent's system prompt automatically — now tells the agent to call `wait_for_message(timeout_secs=N)` at the start of every turn. Push remains as the strictly-better delivery for hosts that opt in (Claude Code with the dev flag or a future allowlist entry), but is no longer load-bearing. Both paths converge on the same `inbox_pop` ack so duplicate-delivery on a push+poll race is impossible: whoever surfaces the message to the agent first pops it, the other side returns empty. Operator knob ------------- `MOLECULE_MCP_POLL_TIMEOUT_SECS` controls per-turn poll blocking (default 2s). 0 disables polling for push-only Claude Code with the dev flag. Above 60 clamps to 60 — protects against an accidental five-minute stall per turn. Resolved fresh on every `initialize` so a relaunch with new env is enough; no wheel rebuild required. Tests ----- - structural pins on the new instructions: `wait_for_message` + `timeout_secs` named, both PUSH PATH / POLL PATH labels present - env-resolution: default fallback, garbage fallback, negative fallback, 60s clamp - operator override: `MOLECULE_MCP_POLL_TIMEOUT_SECS=7` reaches the agent's instructions string - timeout=0 toggles to push-only-mode messaging (no wait_for_message call asked of the agent) - existing pins on push path, reply tools, prompt-injection defense, meta attributes — all preserved Successor to #46. Closure milestone for this PR (per feedback_close_on_user_visible_not_merge.md): launched `claude` against the published wheel, sent a canvas message, observed the agent surfaces the message inline at the start of its next turn without me running `inbox_peek` — verified live before declaring done. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| adapters | ||
| builtin_tools | ||
| lib | ||
| molecule_audit | ||
| platform_tools | ||
| plugins_registry | ||
| policies | ||
| scripts | ||
| skill_loader | ||
| tests | ||
| .coveragerc | ||
| a2a_cli.py | ||
| a2a_client.py | ||
| a2a_executor.py | ||
| a2a_mcp_server.py | ||
| a2a_tools.py | ||
| adapter_base.py | ||
| agent.py | ||
| agents_md.py | ||
| build-all.sh | ||
| config.py | ||
| configs_dir.py | ||
| consolidation.py | ||
| coordinator.py | ||
| Dockerfile | ||
| entrypoint.sh | ||
| events.py | ||
| executor_helpers.py | ||
| heartbeat.py | ||
| inbox.py | ||
| initial_prompt.py | ||
| internal_chat_uploads.py | ||
| internal_file_read.py | ||
| main.py | ||
| mcp_cli.py | ||
| molecule_ai_status.py | ||
| platform_auth.py | ||
| platform_inbound_auth.py | ||
| plugins.py | ||
| preflight.py | ||
| prompt.py | ||
| pytest.ini | ||
| rebuild-runtime-images.sh | ||
| requirements.txt | ||
| runtime_wedge.py | ||
| shared_runtime.py | ||
| smoke_mode.py | ||
| transcript_auth.py | ||
| watcher.py | ||