Skip to content

fix: ACP thinking config, cron delivery dedup, HEARTBEAT_OK, QMD 1.1.6 - #1

Merged
e-mon merged 8 commits into
mainfrom
fix/acp-thinking-config
Mar 12, 2026
Merged

fix: ACP thinking config, cron delivery dedup, HEARTBEAT_OK, QMD 1.1.6#1
e-mon merged 8 commits into
mainfrom
fix/acp-thinking-config

Conversation

@e-mon

@e-mon e-mon commented Mar 12, 2026

Copy link
Copy Markdown
Owner

Summary

  • ACP thinking config: Add isChatModel: true to the ACP session's sendMessageStream call. Without it, resolveAliasChain() never falls back to the chat-base alias, so thinkingConfig: { includeThoughts: true } is missing from API requests. The Gemini API then returns thinking content as regular text (part.thought = undefined) instead of thought-marked parts, causing thought narration to leak into responseText and be displayed to users.
  • HEARTBEAT_OK detection: Relax the regex to tolerate markdown decoration (**HEARTBEAT_OK**, `HEARTBEAT_OK`) and end-of-line appends (...HEARTBEAT_OK) that LLMs sometimes produce.
  • QMD 1.0.7 → 1.1.6: Upgrade to hybrid search with query expansion + vector + BM25 + reranking. Three separate tools (search/vector_search/deep_search) unified into query. Japanese vague queries that returned 0 results on BM25-only now return relevant hits via auto-expansion.
  • Cron delivery dedup: Replace framework-level sendReply with skill-driven geminiclaw_post_message delivery for background jobs. Cron jobs (patrol, daily-briefing, etc.) were posting content via geminiclaw_post_message AND having sendReply deliver responseText to the same homeChannel, causing duplicate messages. CronJob.reply is repurposed as a delivery target hint injected into agent context. Removes config.heartbeat.reply, config.cron.defaultReply, and the legacy postToChannel path in deliverReply.

Context

Test plan

  • Deploy to server and run with gemini-3.1-pro-preview
  • Verify responseText no longer contains thought narration
  • Check debug events file for correct agent_thought_chunk emission
  • Verify QMD qmd_query tool works via MCP (replaces qmd_search/qmd_vector_search/qmd_deep_search)
  • Verify patrol cron posts only once to homeChannel (no duplicate from sendReply)
  • Verify daily-briefing cron delivers via geminiclaw_post_message
  • Verify heartbeat notifications still work (home channel injection in context-builder)
  • Unit tests: 529 passed

🤖 Generated with Claude Code

e-mon and others added 3 commits March 12, 2026 14:11
Hybrid search (query expansion + vector + BM25 + reranking) replaces
the three separate tools (search/vector_search/deep_search) with a
unified `query` tool. Tested: Japanese vague queries that returned 0
results on BM25-only now return relevant hits via auto-expansion.

- Update MCP tool references in AGENTS.md, context-builder, tests
- Recreate patches (RERANK_CONTEXT_SIZE 4096, createMcpServer export)
- Fix serve.ts imports to use createRequire (QMD exports map changed)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Without isChatModel: true in the ACP session's sendMessageStream call,
resolveAliasChain() does not fall back to the chat-base alias, so
thinkingConfig (includeThoughts: true) is never sent to the Gemini API.
This causes the API to return thinking content as regular text parts
(part.thought = undefined) instead of marking them with part.thought = true,
resulting in thought narration leaking into responseText and being
displayed to the user.

Upstream: google-gemini/gemini-cli#21411 (closed but PR #21412 unmerged)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
LLMs sometimes append HEARTBEAT_OK without a preceding newline or wrap
it in bold/code markers (**HEARTBEAT_OK**, `HEARTBEAT_OK`). Strip
markdown decoration and match at end of any line instead of requiring
a standalone line.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@e-mon e-mon changed the title WIP: fix(patch): ACP thinking config leak fix: ACP thinking config leak + HEARTBEAT_OK detection Mar 12, 2026
@e-mon e-mon changed the title fix: ACP thinking config leak + HEARTBEAT_OK detection fix: ACP thinking config + HEARTBEAT_OK detection + QMD 1.1.6 upgrade Mar 12, 2026
e-mon and others added 2 commits March 12, 2026 15:40
Node 25.8 enforces ESM top-level await restrictions on require().
QMD's store.js uses top-level await, so createRequire fails with
ERR_REQUIRE_ASYNC_MODULE. Switch back to dynamic import() with
@ts-expect-error to suppress TS module resolution errors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@ts-expect-error fails when TS doesn't flag the import as an error
(varies by environment/TS config). @ts-ignore works in both cases.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@e-mon
e-mon force-pushed the fix/acp-thinking-config branch from 3b3c7c4 to fdf6cb8 Compare March 12, 2026 06:42
e-mon and others added 3 commits March 12, 2026 15:44
Add silent: true to tasks that don't need their commands printed
(install, start, stop, status, logs, setup sub-commands).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Background jobs (cron/heartbeat) previously had two delivery paths:
1. Skills posting via geminiclaw_post_message (explicit)
2. Framework sendReply posting responseText to reply target (implicit)

Both targeted the same homeChannel, causing duplicate messages.

This change unifies delivery: all background jobs post results via
geminiclaw_post_message. The CronJob.reply field is repurposed as a
delivery target hint injected into agent context, rather than driving
framework-level sendReply.

Removed:
- buildCronReply / resolveHomeChannel (cron-scheduler.ts)
- buildHeartbeatReply (heartbeat.ts)
- config.heartbeat.reply / config.cron.defaultReply (schema.ts)
- Legacy postToChannel path in deliverReply (reply.ts)
- AgentRunEventData.reply object field

Added:
- AgentRunEventData.deliveryTarget (platform:channelId string)
- ContextBuilder.resolveHomeChannel() helper
- Cron mode context injection with delivery target instruction

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove unused messageId/threadTs from CronJob.reply
- Simplify hasReplyTarget to one-liner

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@e-mon e-mon changed the title fix: ACP thinking config + HEARTBEAT_OK detection + QMD 1.1.6 upgrade fix: ACP thinking config, cron delivery dedup, HEARTBEAT_OK, QMD 1.1.6 Mar 12, 2026
@e-mon
e-mon marked this pull request as ready for review March 12, 2026 09:18
@e-mon
e-mon merged commit 283a271 into main Mar 12, 2026
4 checks passed
@e-mon
e-mon deleted the fix/acp-thinking-config branch March 12, 2026 09:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant