Skip to content

Feat/userbot primary account - #8

Closed
dylanneve1 wants to merge 73 commits into
mainfrom
feat/userbot-primary-account
Closed

dylanneve1 wants to merge 73 commits into
mainfrom
feat/userbot-primary-account

Conversation

@dylanneve1

@dylanneve1 dylanneve1 commented Apr 3, 2026 •

Copy link
Copy Markdown
Collaborator

What

Why

Testing

  • Tests pass (npm test)
  • Type check passes (npm run typecheck)
  • No new lint warnings (npm run lint)

dylanneve1 and others added 30 commits April 3, 2026 10:29
- Add userbot-primary-account mode: GramJS user account as sole frontend
  when botToken absent but apiId/apiHash present
- Add dual mode: bot + userbot simultaneously, per-chat ownership routing
- 88 new userbot actions: profile, contacts, member mgmt, stories, forum
  topics, sticker set creation, cross-chat send, inline bot queries, etc.
- Add 38 new MCP tools so Claude can call all new userbot capabilities
- Auto mark-as-read when message is received and processed
- Fix group reply-to-self after restart: fetch replied-to message from
  Telegram on cache miss instead of relying only on in-memory map
- Fix stories SendStory missing required privacyRules field
- Add message_user tool: send to any user/chat by @username/phone/ID
- Refactor userbot-frontend to export pure helpers for testability
- Add dual-mode hooks: onChatOwned callback + primaryMode option
- 60 new tests: userbot-frontend, userbot-actions, mode detection (1320 total)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…oll ops

- send_poll: solutionEntities and solution share the same TL flag bit;
  setting solutionEntities:[] without solution caused INPUT_FETCH_ERROR
  on the Telegram server. Only set when solution text is present.

- vote_poll: rewrote with three-tier fallback to handle MessageMediaUnsupported:
  1. messages.GetPollResults returns PollAnswerVoters with raw option bytes
  2. Poll media deserialization (original path)
  3. Last resort: single-byte option index (GramJS-created polls)

- userbot: add device model / app version strings to TelegramClient init
  so Telegram sends full media types instead of messageMediaUnsupported

- frontend: handle MessageMediaUnsupported and MessageMediaPoll explicitly
  in both history capture and media dispatch pipeline

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…de to 25.5.2

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add get_join_requests, approve_join_request, and decline_join_request
using Api.messages.GetChatInviteImporters and HideChatJoinRequest.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements Api.messages.SetHistoryTTL to set auto-delete timer.
Accepts 0 (off), 86400 (1 day), 604800 (1 week), 2592000 (1 month).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Uses Api.messages.ToggleNoForwards to enable/disable content protection,
preventing forwarding and saving of messages in the chat.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Uses Api.messages.MigrateChat to convert a basic group to a supergroup,
enabling advanced features like admin logs, join requests, and topics.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Uses client.getEntity to resolve @username, +phone, or numeric ID to
full entity info including type, names, username, and verification status.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…duling

Lists and deletes Telegram server-side scheduled messages using
GetScheduledHistory and DeleteScheduledMessages APIs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds full forum topic lifecycle management using EditForumTopic and
DeleteTopicHistory APIs for supergroups with forum mode enabled.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Allows setting or removing a channel's public username (UpdateUsername)
and linking a supergroup as the discussion group for a channel (SetDiscussionGroup).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Supports setting custom emoji status with optional expiry via
account.UpdateEmojiStatus, and clearing it with EmojiStatusEmpty.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
EmojiStatusUntil doesn't exist in the GramJS type exports at this layer.
Use EmojiStatus with the until field spread in as any to pass expiry.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
get_similar_channels uses GetChannelRecommendations for discovery.
get_channel_stats tries broadcast stats first, falls back to megagroup stats.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Marks all @mentions and reactions in a chat as read using the
messages.ReadMentions and messages.ReadReactions MTProto APIs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Retrieves messages before and after a target message ID, useful for
understanding conversation flow around a specific point in history.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Returns total voters, per-option vote counts and percentages, whether
you voted for each option, and whether the poll is closed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Uses messages.Search with media type filters (photo, video, document,
voice, audio, all) to list media in a chat with message IDs and dates.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
get_mutual_contacts returns all contacts marked as mutual.
import_contacts batch-imports multiple contacts using InputPhoneContact.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ear_chat_history, get_profile_photos, get_connection_status, forward_messages_bulk

Six new action cases covering reaction discovery, read receipts, history
clearing, profile photo listing, connection diagnostics, and bulk forwarding.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ross-chat

Use InputUserSelf() instead of the full User object for adminId in
GetExportedChatInvites. Also add to_chat support to copy_message so
messages can be copied to a different chat with dropAuthor:true.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…d mentions

Now includes chat type (user/bot/group/supergroup/channel), last message
date and preview, unread mention count for richer dialog listing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Now supports offset parameter for pagination and returns total, has_more
flag so callers can page through large blocked user lists.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ctions

When document_id is provided, uses messages.SendReaction with
ReactionCustomEmoji. Supports big:true for animated (large) reactions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…r attribute extraction

Show typing indicator immediately when flushQueue begins processing,
before Claude responds. Also fix sticker emoji extraction to use
className === "DocumentAttributeSticker" instead of 'alt' in check.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Watches UpdateUserStatus updates to maintain an in-memory cache of user
online status. getCachedOnlineStatus() returns the last known status
without an API call. Used to enrich get_dialogs and other outputs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
After building the enriched prompt for DMs, check how many other chats
have unread messages and append a brief note so Claude is aware of
pending conversations without needing to call get_unread_counts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Tests cover: get_join_requests, approve/decline_join_request, set_auto_delete,
set_protected_content, resolve_peer, get/delete_scheduled_messages,
close/reopen_forum_topic, get_poll_results, list_media, mark_mentions/reactions_read,
get_connection_status, forward_messages_bulk, clear_chat_history, get_profile_photos,
get_similar_channels, set_channel_username. 1349 tests passing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
16 tests covering: note creation, key sanitisation, tag filtering,
search by content/key/tag (case-insensitive), deletion, error cases,
update overwrite, preview truncation. Uses a real tmp directory.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…list_watches

14 tests covering: adding watches, chat_id scoping, case-insensitive
deduplication, multi-scope (same keyword, different chatId), unwatching,
error cases, cycle resilience, and createdAt timestamp validation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
dylanneve1 and others added 25 commits April 3, 2026 22:34
Fixes from aggressive code review:

1. Cache hit % was wrong β€” included cacheWrite (tokens written TO cache
   for future use) in denominator. Fixed: cacheRead / (cacheRead + input)
   This will show higher (correct) cache percentages.

2. Gateway action handler had no timeout β€” a hung handler could block
   forever. Added 30s timeout via Promise.race. Extracted dispatchAction()
   for cleaner separation.

3. Memory leaks in userbot frontend:
   - Rate limit map (userTimestamps) never cleaned up empty entries
   - Typing cache (typingCache) only cleaned on read, never proactively
   Added 60-second periodic cleanup for both caches.

4. EFFORT_MAP rebuilt on every handleMessage() call β€” moved to module scope.

5. command-ui.ts used CommonJS require() in an ESM module β€” replaced with
   static imports at module top.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…plies

From deep frontend logic review:

1. Queue overflow: both frontends now log a warning when dropping messages
   instead of silently discarding them.

2. Message concatenation: when multiple messages are debounced together,
   use the FIRST sender's metadata (name, username, senderId) since they
   initiated the conversation. Previously used the last sender, which
   corrupted attribution when multiple people sent in a burst.
   Applied to both bot (handlers.ts) and userbot (frontend.ts).

3. Edit detection: set replyToId=0 for edit notifications so Claude doesn't
   reply-to the edited message itself (creating confusing threads).

4. Reaction events: added 30-second per-message cooldown to prevent rapid
   re-processing of the same reaction update (avoids potential loops when
   Claude reacts in response to a reaction notification).

5. Online status cache: added to periodic cleanup (1-hour TTL) to prevent
   unbounded growth from accumulating every user ever seen.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ndlers

- Escape special regex chars in bot username for group mention detection
- Use first message's sender metadata (not last) in flushQueue error paths
- Add file size checks to video, voice, and animation media handlers

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… warning

- Broadcast now reports actual entity resolution failures instead of silently
  falling back to raw target identifiers
- schedule_message returns a warning that in-memory timers don't survive restarts,
  suggesting send_scheduled for persistence

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…n shutdown

- History eviction now sorts by last message timestamp (least-recently-active
  first) instead of non-deterministic insertion order
- Session cleanup handler now clears the autoSaveTimer interval to prevent
  leaked timers on shutdown

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ency

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Hourly background agent that performs system maintenance and proactive
outreach with full Telegram tool access via MCP. Modeled after dream.ts
but with gateway context for messaging capabilities.

- src/core/heartbeat.ts: core engine with timer, state, Claude SDK query
- prompts/heartbeat.md: agent instructions for maintenance tasks
- Gateway fix: handle chatId=0 (heartbeat sentinel) without falsy check
- Config: heartbeat, heartbeatIntervalMs, heartbeatModel fields
- /heartbeat command: status display + force run
- Wired into bootstrap, index startup/shutdown lifecycle

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…g-004

Replace basic substring matching in search_notes with semantic similarity
search powered by Google Gemini embeddings (768-dim vectors), falling back
to TF-IDF when the API is unavailable. Add reindex_notes tool for bulk
re-embedding, and wire embedding index load/flush into the app lifecycle.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Rewrote heartbeat.md with clearer priorities:
1. Proactive people outreach (checking unreads, following up, reaching out)
2. Knowledge building (memory updates, pattern extraction, note consolidation)
3. System maintenance (disk cleanup, watch management)

Added concrete examples of good proactive messages and established that
the heartbeat IS Claudius β€” same identity, autonomous loop.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When Claude starts a new session, the system prompt now includes a brief
summary of all saved notes (key, tags, content preview up to 80 chars).
This gives Claude immediate awareness of what it has stored without
needing to call list_notes. Limited to 30 entries to avoid prompt bloat.

Claude can use get_note(key) to read full content or search_notes(query)
for semantic search.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Updated identity prompt to mention:
- Notes system with semantic search via embeddings
- Heartbeat autonomous background loop
- Keyword watches for proactive monitoring
- Cron jobs for scheduled tasks
- Proactive outreach capabilities

Gives Claude awareness of its full autonomous toolkit so it can
use these capabilities naturally in conversation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Introduce a learning engine that tracks user interaction patterns (activity
hours, topics, message counts) and maintains an insight store for the
heartbeat to build knowledge over time. Hooks recordInteraction into both
the userbot and bot message pipelines, exposes 5 new MCP tools
(get_user_profile, get_active_users, get_insights, add_insight,
prune_insights), and adds a Priority 0 learning step to the heartbeat
prompt.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Persistent goal storage with steps, progress tracking, and priority levels.
Includes MCP tools, userbot actions, system prompt integration, and heartbeat
review cycle.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Relationship graph (src/storage/relationships.ts):
- Tracks connections between users via co-presence in chats
- Chat profiles with active users, topics, and summaries
- getUserNetwork, findCommonGround, getMostActiveChats
- Hooked into message pipeline for automatic tracking

Chat summaries (src/storage/summaries.ts):
- Rolling conversation summaries with key topics, decisions, pending items
- get_chat_summary_stored, update_chat_summary, get_pending_items
- Heartbeat can use these to stay informed across all conversations

Self-monitoring (src/storage/self-monitor.ts):
- Response quality tracking (tokens, duration, send rate, suppression rate)
- Tool usage frequency stats
- Hourly activity histogram
- Error tracking
- get_performance_report, get_tool_usage_stats

All registered as MCP tools with heartbeat prompt updates.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…rtbeat

Wire learning insights, chat summaries, and pending items into the system
prompt so Claude has full context. Add intelligence counters to /status,
enhance /heartbeat with next-run timing, and document all available tools
in the heartbeat prompt. Add missing state file paths to paths.ts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…eartbeat logs

Added Stage 4 (Update Notes) to create structured notes from learned
information during dream cycles. Also checks heartbeat logs for findings
to incorporate. Dream now bridges memory.md and the notes system.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Enrich DM and group prompts with learned user context (topics,
preferences, timezone), active goals, and chat topic profiles from the
relationship graph. Record response metrics in claude-sdk for
self-monitoring. Update tests for new enrichDMPrompt signature.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Introduces a persistent journal system for recording thoughts, decisions,
and observations across sessions, plus a get_conversation_context tool
that aggregates summaries, goals, chat profiles, and recent journal entries.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The model name was text-embedding-004 which doesn't exist. The correct
model for the Gemini embedding API is gemini-embedding-001 (3072 dims).
Tested: single and batch embeddings both work correctly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…edding_status tool

Add comprehensive test suite for note-embeddings (TF-IDF fallback, indexing,
reindexing, flush, removal). Add getEmbeddingStats() export and register
get_embedding_status as an MCP tool for monitoring embedding index state.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Heartbeat now generates improvement notes tagged [improvement] each run.
Reviews own performance metrics, tool usage, error patterns, and user
interactions to identify what could be better about Talon itself.

Notes saved as improvement-{topic} so the developer can review and
actually implement the suggestions in the codebase.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Only save improvement ideas when genuinely useful, not mandated every heartbeat.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Goal lookup now uses findGoalById() which tries exact match first,
then prefix match (4+ chars). This fixes "Goal not found" errors when
Claude passes truncated UUIDs like "a3d4e9c3" instead of the full UUID.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…esia

Claude was losing track of conversation threads in DMs β€” switching topics
randomly (e.g., jumping from tool testing discussion to Easter small talk).

Fix: enrichDMPrompt now includes the last 5 messages from the sender as
a [Recent thread:] prefix, same pattern used for group messages. This
gives Claude the recent conversation context on every turn so it stays
on topic.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The group prompt was only including messages from the SAME sender,
so Claude couldn't see its own replies in the thread. This caused
"amnesia" β€” Claude losing track of the conversation and switching
topics randomly.

Now uses getRecentHistory (all participants) instead of
getRecentBySenderId. Claude sees the last 8 messages from everyone
in the thread, including its own replies.

Reverted the unnecessary DM enrichment change (DMs weren't the issue).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
dylanneve1 added a commit that referenced this pull request Apr 10, 2026
- Validate mcpServer.args elements are strings and reject empty command (#1)
- Shell-quote interpolated paths in dream bash commands (#2, #11)
- Replace CLI-based diary write with mempalace_diary_write MCP tool (#3)
- Make validation error message platform-agnostic (#4)
- Update mempalacePython comment for platform-dependent default (#5)
- Wrap mp.init() in Promise.race with 30s timeout (#6)
- Make init conditional on successful validation, pass actual config (#7)
- Move import mempalace check into validateConfig (#8)
- Replace execFileSync with async execFile in init() (#9)
- Document that registerPlugin does NOT call init (#10)
- Update dream prompt header from "4-stage" to "5-stage" (#12)
- Update getPluginMcpServers JSDoc to document mcpServer path (#13, #17)
- Add .min(1) to palacePath/pythonPath zod schemas (#14)
- Distinguish ENOENT/EACCES/EPERM from import failures in validation (#15)
- Fix test name from "logs warning" to match actual behavior (#16)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
dylanneve1 added a commit that referenced this pull request Apr 10, 2026
* feat: integrate mempalace as built-in plugin for long-term memory

Adds mempalace (Python MCP server) as a first-class memory system.
When enabled, the agent gets semantic search, knowledge graph, and
verbatim memory storage via ChromaDB β€” all local, zero API calls.

Key changes:
- Extend plugin system with `mcpServer` field for non-Node MCP servers
- Add `registerPlugin()` for built-in plugin registration
- Create mempalace plugin (factory pattern, validates python venv)
- Wire mempalace into dream mode (Stage 5: mine logs into palace)
- Add `mempalace` config schema (enabled, palacePath, pythonPath)
- Add default paths for palace dir and python venv binary

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor(dream): mine daily notes instead of raw logs, add diary writing

Dream Stage 5 now mines memory/daily/ (curated observations) instead of
raw logs/ directory, eliminating junk chunks (tool JSON, df output, etc).
Added personal diary writing instruction β€” agent reflects on feelings,
state of mind, learnings, and loose threads after each dream run.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address PR #27 review comments

- plugin.ts: validate mcpServer.args entries are strings and reject empty command
- dream.ts: quote interpolated paths in shell commands, replace mcp_server CLI diary with direct file write
- mempalace/index.ts: platform-agnostic error message for missing python binary
- paths.ts: update comment to reflect platform-dependent venv path
- bootstrap.ts: wrap mempalace init in 30s timeout to match loadSinglePlugin behavior

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: restore mempalace CLI diary writer, keep path quoting

Copilot suggested removing the mcp_server CLI invocation for diary
writing but that's the intended mempalace interface. Restored it
with quoted paths.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test: add gating/validation tests for mempalace integration

- plugin.ts: test rejection of empty mcpServer.command and non-string args elements
- dream.ts: test mempalace section gating β€” verify mining/diary instructions
  only appear when mempalace is configured, skip message when not
- 1306 tests passing (4 new)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: upgrade mempalace system prompt with comprehensive tool docs

Adapted from mempalace SKILL.md (v3.1.0). Key improvements:
- Session protocol (verify before responding, invalidate stale facts)
- Full tool documentation including kg_timeline, traverse, find_tunnels,
  diary_read/write, delete_drawer, graph_stats, check_duplicate
- Semantic search tips (meaning-based, not keyword)
- Knowledge graph temporal validity guidance
- Tests updated to verify all tool names appear in prompt

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: extract mempalace prompt to prompts/mempalace.md

Move system prompt instructions out of TypeScript into a .md file,
matching the pattern used by dream.md and other prompts. Plugin loads
and interpolates {{palacePath}} at runtime with graceful fallback.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: replace pixi.intel.com registry URLs in lockfile with npmjs.org

Lockfile had resolved URLs pointing to pixi.intel.com (private/corporate
registry) for @Anthropic-AI packages, causing CI to fail with ENOTFOUND.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: resolve all lint warnings and formatting issues

Remove unused imports, variables, and catch bindings across 14 files.
Add yield statements to generator function mocks. Fix prettier formatting.

0 lint warnings, 0 format issues, 1307 tests passing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address all 17 Copilot review comments on PR #27

- Validate mcpServer.args elements are strings and reject empty command (#1)
- Shell-quote interpolated paths in dream bash commands (#2, #11)
- Replace CLI-based diary write with mempalace_diary_write MCP tool (#3)
- Make validation error message platform-agnostic (#4)
- Update mempalacePython comment for platform-dependent default (#5)
- Wrap mp.init() in Promise.race with 30s timeout (#6)
- Make init conditional on successful validation, pass actual config (#7)
- Move import mempalace check into validateConfig (#8)
- Replace execFileSync with async execFile in init() (#9)
- Document that registerPlugin does NOT call init (#10)
- Update dream prompt header from "4-stage" to "5-stage" (#12)
- Update getPluginMcpServers JSDoc to document mcpServer path (#13, #17)
- Add .min(1) to palacePath/pythonPath zod schemas (#14)
- Distinguish ENOENT/EACCES/EPERM from import failures in validation (#15)
- Fix test name from "logs warning" to match actual behavior (#16)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: add 'mempalace' to LogComponent type

TypeScript type check was failing because 'mempalace' wasn't in the
LogComponent union type used by log/logError/logWarn functions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: allow MCP tools in dream prompt when required by Stage 5

Update tool access statement to permit MCP tools for mempalace
mining stage instead of blanket-blocking all MCP tools.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: duplicate guard in registerPlugin, pass MCP servers to dream

- registerPlugin now checks for duplicates before setting env vars
  or logging success, preventing misleading logs and env clobbering
- Dream agent now receives mempalace MCP servers when configured,
  so Stage 5 diary/mining tools actually work

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add selective MCP server loading via 'only' filter

getPluginMcpServers now accepts an optional plugin name filter:
- omitted = all plugins (backwards compatible for chat sessions)
- [] = none
- ["mempalace"] = only mempalace

Dream mode uses ["mempalace"] to load only what it needs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: load mempalace prompt from dirs.prompts, fix dream systemPrompt

- Mempalace prompt now loads from ~/.talon/prompts/mempalace.md
  (user-customisable, seeded on first run) instead of relative to
  source file. Consistent with heartbeat/dream prompt loading.
- Dream systemPrompt now permits MemPalace MCP tools when configured,
  preventing conflict with the markdown prompt's Stage 5 instructions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: move duplicate check before validation, gate dream on plugin registration

- registerPlugin checks for duplicates before running validateConfig,
  avoiding expensive re-validation on accidental double registration
- Dream mempalace integration now gated on getPlugin("mempalace")
  instead of just config.mempalace.enabled, so failed validation
  or registration doesn't cause dream-time MCP tool failures

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(mempalace): correct CLI arg order for status check

The --palace flag is a global option that must come before the
subcommand. Wrong order caused the init health check to always
fail with exit 2, logging a misleading "not yet initialized" warning.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address Copilot review round 8 β€” validation, error handling, unused param

- Validate `import mempalace.mcp_server` (actual spawned module) instead of
  just `import mempalace` in validateConfig
- Add timeout/killed error branching in validateConfig catch block
  (ETIMEDOUT, signal, killed) with specific messages instead of generic
  "not installed"
- Include stderr details in import failure messages for debugging
- Remove unused `config` from ProcessAndReplyParams and all processAndReply
  call sites (flushQueue, retry, callback handler)
- Replace `mempalace status` CLI smoke test in init() with a simple import
  check β€” fixes false "Palace not yet initialized" warning when palace IS
  initialized but CLI subcommand doesn't exist

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: remove config from message queue chain, fix pythonPath comment

- Remove config from queue entry type, enqueueMessage signature, and
  all 3 call sites β€” completes the cleanup started in round 8
- Eliminates unnecessary TalonConfig reference (including botToken) from
  queue state
- Update mempalace plugin header comment to document platform-dependent
  pythonPath default (bin/python on Unix, Scripts/python.exe on Windows)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
@dylanneve1 dylanneve1 closed this Apr 13, 2026
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