Commit Graph

55 Commits

Author SHA1 Message Date
Fodesu a2cb5939d7 fix(discord): rm reason in final message (#220) 2026-03-09 23:34:34 +08:00
Menci 36d50738b5 fix(channel): consistent markdown rendering across all Telegram paths (#210)
- Extract ContainsMarkdown to shared channel package
- Auto-detect markdown in normalizeOutboundMessage and MCP send tool
- Apply markdown-to-HTML conversion during streaming deltas, not just
  on the final message
- Remove resolveTelegramParseMode which incorrectly returned Telegram's
  native "Markdown" mode instead of converting to HTML
- Fix all 14 Telegram send/edit paths for consistent parse mode handling
- Reset parseMode for plain-text error messages to avoid HTML corruption
2026-03-09 13:06:44 +08:00
BBQ 3739def43f fix(text): avoid breaking UTF-8 during truncation
Use rune-aware truncation for user-facing text and log previews so multibyte content is not corrupted in memory context, Telegram messages, or diagnostics.
2026-03-09 12:43:57 +08:00
Menci 09cdb8c87f refactor(telegram): reduce code duplication and improve readability
- Extract parseTelegramTarget helper to consolidate duplicated @username
  vs numeric chat ID parsing from 6+ locations (builder functions,
  sendTelegramTextReturnMessage, sendTelegramAttachmentImpl)
- Extract Config.baseURL() to eliminate duplicate base URL resolution
  between apiEndpoint() and fileEndpoint()
- Refactor stream.go Push method: extract resetStreamState(),
  deliverFinalText(), and per-event-type sub-methods (pushDelta,
  pushFinal, pushToolCallStart, pushAttachment, pushPhaseEnd,
  pushError), reducing the 200-line switch-case to a clean dispatcher
- Use pushFinal's existing getBot() instead of duplicating parseConfig +
  getOrCreateBot
- Replace sort.SliceStable with slices.SortStableFunc + cmp.Compare
- Replace strings.Index + manual slicing with strings.Cut in
  decodeDataURLBytes, ResolveAttachment, and parseTelegramUserInput
2026-03-09 10:03:12 +08:00
Ringo.Typowriter e6a6dbe3f6 feat(channel): add QQ channel support and image message pipeline (#199)
* feat(channel): add qq adapter and outbound delivery

* feat(channel): ingest inbound qq messages

* feat(web): expose qq channel in management ui

* feat(channel): support qq attachment ingestion

* fix(mcp): fail read raw immediately for missing files

* fix(agent): parse inline image data into native image parts

* test(agent): align read_media tool tests with SDK options

* fix(channel): harden qq image delivery and reconnect loop

Avoid data URLs for qq channel images, reset reconnect backoff after healthy sessions, and fall back gracefully for malformed public image URLs.

* fix(channel): restore qq media delivery and target resolution

* fix(qq,mcp,agent): fix message/qq regressions and pass go lint

* fix(qq,agent): validate inline base64 and sync heartbeat seq

* fix(qq): validate remote voice mime for upload checks

* fix(qq): fall back intents and restore adapter wiring

* fix(qq): prevent final text leakage and dedupe persisted inbound query
2026-03-07 17:12:06 +08:00
0x24a ac405c49e2 fix(channel): return success when bind code is re-checked by same identity (#201)
* fix(channel): return success when bind code is re-checked by same identity

* style: run gofmt
2026-03-07 15:07:32 +08:00
BBQ 3feb03aca7 ci: add go lint and race test workflow (#187) 2026-03-05 11:25:33 +08:00
Fodesu 711cee7682 fix(channel): split long streaming messages at manager level (#168) (#182)
Split long AI responses into multiple platform messages during streaming
instead of truncating them. The manager counts accumulated delta runes
and opens a new stream when approaching the platform's TextChunkLimit.
Uses a soft/hard limit strategy that prefers splitting at sentence ends
or line breaks over cutting mid-sentence.

- Add pushDelta with soft (75%) / hard (100%) limit and natural break
  point detection
- Add splitStream, pushFinalAfterSplit, pushFinalWithChunking helpers
- Fix Discord adapter to use RuneCount Message Length
- Add tests for delta splitting, natural breaks, and final handling
2026-03-04 17:57:55 +08:00
Menci a124cde8e2 feat(telegram): add in-reply-to and forwarded-from header and clarify user name (#177) 2026-03-04 17:57:12 +08:00
Ringo.Typowriter 0a2a17ecc8 feat(agent): add readMedia tool for model to view the image (#165)
* feat(agent): add readMedia tool for loading local images into model
context

* feat(channel/inbound): include container attachment refs in inbound
query

* fix(agent): preserve ImagePart literal typing in buildNativeImageParts

* chore: rename tool

---------

Co-authored-by: 晨苒 <16112591+chen-ran@users.noreply.github.com>
2026-03-04 11:24:01 +08:00
Acbox f0517a3a1f fix: inbox indirectly push notidy item into context 2026-03-03 20:38:36 +08:00
Menci b1925bf2be feat(telegram): use sendMessageDraft for streaming in private chats (#174)
* feat(telegram): use sendMessageDraft for streaming in private chats

Use Telegram Bot API 9.3's sendMessageDraft to stream partial messages
with smooth animation in private chats, replacing the sendMessage +
editMessageText approach. Group/channel chats keep the existing
edit-based streaming.

- Add sendTelegramDraft() for the sendMessageDraft API
- Detect private chats via conversation_type metadata in OpenStream
- Use 300ms throttle for drafts (vs 5s for edits)
- Send permanent messages at tool call boundaries and on final event
- Reset buffer atomically in StreamEventFinal to prevent duplicate
  messages when multiple final events fire (one per assistant output)

* test(telegram): improve draft mode test assertions

Add sendTextForTest hook for sendTelegramTextReturnMessage to enable
direct assertion of send calls. Clean up residual unused variables
and replace indirect assertions with explicit mock-based verification.
2026-03-03 16:01:18 +08:00
BBQ 802dfd995f feat(telegram): support custom API base URL for reverse proxy setups (#160)
Allow configuring a custom Telegram Bot API base URL (`apiBaseURL`) per
channel, enabling users behind restricted networks to route requests
through a reverse proxy (e.g. Nginx, Cloudflare Workers).

Both API calls and file downloads respect the configured endpoint.
When omitted, the official https://api.telegram.org is used.

Closes #159
2026-03-02 15:04:20 +08:00
斬風千雪 b82444759a fix(telegram): several fixes of typing action in stream message (#136) 2026-03-01 14:11:32 +08:00
Acbox Liu fe10abf3fc refactor: inbox (#137)
* refactor: inbox

* fix: migrations

* fix: migrations
2026-02-26 20:16:02 +08:00
Fodesu 5aefccd7cc feat: support discord attacchment file, assetService 2026-02-25 16:30:43 +08:00
Fodesu 87a4be7439 fix: discord channel stream ignore Reasoning content 2026-02-25 16:29:57 +08:00
Ran 5e12b5a53f fix: ensure unifying on hardcoded /data mount path 2026-02-24 03:35:27 +08:00
Ringo.Typowriter 29e76322cc feat(feishu): add webhook inbound mode, region support, and callback/attachment enhancements (#107) 2026-02-23 21:57:34 +08:00
Fodesu df12d94171 fix: replay methion 2026-02-23 18:38:07 +08:00
Acbox Liu 17cd077f34 feat: add thinking support (#100)
* feat: add thinking support

* feat: improve thinking block render in web and filter thinking content in channels

* fix: migrate
2026-02-23 14:41:27 +08:00
Ran 5a08b280ab fix: double reply bug 2026-02-23 05:55:20 +08:00
Fodesu 51acb4b546 feat: add replay Message 2026-02-23 05:55:20 +08:00
Fodesu 77ff24c6fd feat(platforms): add discord channel support 2026-02-23 05:55:20 +08:00
Acbox 44ab3792d2 fix(channel): create new message when tool calling 2026-02-23 00:31:59 +08:00
Acbox ac929f9f44 feat: add message id in user header 2026-02-23 00:06:15 +08:00
Acbox Liu c591af14b0 feat: bot inbox (#77)
* feat: bot inbox

* feat: unified header

* fix: missing tool_call usage

* feat: add group name in header
2026-02-22 01:27:24 +08:00
Acbox 7b12fb0b0c fix: send file out of /data/media failed 2026-02-21 00:04:38 +08:00
Acbox cb5d2c5fab fix: send message in group failed 2026-02-20 22:47:02 +08:00
Acbox 1a78ba3f53 feat: add platform metadata in contacts 2026-02-20 22:19:15 +08:00
Acbox 82cc9c357f feat: support attachment send to tool send 2026-02-20 22:04:00 +08:00
Acbox 6b7c3db952 refactor: process user header in go side 2026-02-20 21:40:13 +08:00
Ringo.Typowriter 53f080503c fix(telegram): aggregate media_group inbound and preserve ordering with (#69)
attachment fallback query
2026-02-19 17:14:12 +08:00
BBQ bc374fe8cd refactor: content-addressed assets, cross-channel multimodal, infra simplification (#63)
* refactor(attachment): multimodal attachment refactor with snapshot schema and storage layer

- Add snapshot schema migration (0008) and update init/versions/snapshots
- Add internal/attachment and internal/channel normalize for unified attachment handling
- Move containerfs provider from internal/media to internal/storage
- Update agent types, channel adapters (Telegram/Feishu), inbound and handlers
- Add containerd snapshot lineage and local_channel tests
- Regenerate sqlc, swagger and SDK

* refactor(media): content-addressed asset system with unified naming

- Replace asset_id foreign key with content_hash as sole identifier
  for bot_history_message_assets (pure soft-link model)
- Remove mime, size_bytes, storage_key from DB; derive at read time
  via media.Resolve from actual storage
- Merge migrations 0008/0009 into single 0008; keep 0001 as canonical schema
- Add Docker initdb script for deterministic migration execution order
- Fix cross-channel real-time image display (Telegram → WebUI SSE)
- Fix message disappearing on refresh (null assets fallback)
- Fix file icon instead of image preview (mime derivation from storage)
- Unify AssetID → ContentHash naming across Go, Agent, and Frontend
- Change storage key prefix from 4-char to 2-char for directory sharding
- Add server-entrypoint.sh for Docker deployment migration handling

* refactor(infra): embedded migrations, Docker simplification, and config consolidation

- Embed SQL migrations into Go binary, removing shell-based migration scripts
- Consolidate config files into conf/ directory (app.example.toml, app.docker.toml, app.dev.toml)
- Simplify Docker setup: remove initdb.d scripts, streamline nginx config and entrypoint
- Remove legacy CLI, feishu-echo commands, and obsolete incremental migration files
- Update install script and docs to require sudo for one-click install
- Add mise tasks for dev environment orchestration

* chore: recover migrations

---------

Co-authored-by: Acbox <acbox0328@gmail.com>
2026-02-19 00:20:27 +08:00
斬風千雪 cd8cb59236 improvement(telegram): add ellipsis and "typing" action in streamed message (#59) 2026-02-17 19:13:55 +08:00
BBQ df7876a30c feat: add media asset system, channel lifecycle refactor, and chat attachments (#54) 2026-02-17 19:06:46 +08:00
Acbox 38753ef054 refactor: channel tools 2026-02-15 17:48:20 +08:00
Ran 399c6eb4f1 Merge branch 'pr/46' 2026-02-15 03:49:23 +08:00
Ran 7817ec8147 fix(web): channel switch failure
Also add webui memory page
2026-02-14 07:30:21 +08:00
Fodesu fc42e717a7 chore: fix typos 2026-02-13 22:06:56 +08:00
BBQ f3ea18a2da feat(telegram): add processing reaction and fix reply-to-bot trigger
Add ProcessingStatusNotifier implementation: show 👀 reaction while
processing, remove on completion/failure. Fix isReplyToBot to match
only the current bot (bot.Self.ID) instead of any bot, preventing
multiple bots from responding to the same reply. Add rune-safe text
truncation for Telegram message length limit.
2026-02-13 20:45:14 +08:00
BBQ b3c869f0ff fix(telegram): sanitize text to valid UTF-8 before sending to API
Strip invalid UTF-8 byte sequences in sendTelegramTextReturnMessage and
editTelegramMessageText to prevent "text must be encoded in UTF-8" errors
that abort the stream mid-response.
2026-02-13 20:26:27 +08:00
BBQ 670698090f fix(route): handle concurrent route creation race condition
Catch unique constraint violation (SQLSTATE 23505) during route creation
in ResolveConversation and fall back to Find, preventing duplicate key
errors when concurrent inbound messages hit the same chat simultaneously.
Add shared IsUniqueViolation helper to internal/db.
2026-02-13 20:26:22 +08:00
BBQ f1d53e1c2c fix(telegram): improve stream edit throttle and 429 rate limit handling
Increase edit throttle from 250ms to 1500ms to respect Telegram per-chat limits,
remove newline bypass that effectively disabled throttling, add dedicated
editStreamMessageFinal with retry for final message delivery, and simplify
editTelegramMessageText by removing blocking sleep in favor of caller-level retry.
2026-02-13 20:21:10 +08:00
BBQ c46f284556 fix(telegram): handle stream edit errors and 429 rate limit
- Treat 400 "message is not modified" as success to avoid user-facing error
- On 429: sleep retry_after and retry once in editTelegramMessageText;
  stream backs off lastEditedAt and returns nil
- Require error code 400 for message-not-modified check; add production
  error string to unit tests
- Lower base throttle to 250ms; add test hooks and tests for 429 retry
  and stream backoff
2026-02-13 19:52:22 +08:00
BBQ faaadf14c5 feat(channel): pass conversation type through to agent gateway and persist in route
Propagate conversation type (direct/group/thread) from channel adapters
all the way to the agent prompt. Store conversation_type on bot_channel_routes
so the bot knows whether a message originates from a p2p chat, group, or thread.

Schema changes are folded into the 0001 init migration (destructive update).
2026-02-13 06:22:24 +08:00
BBQ 85251a2905 refactor(core): codebase quality cleanup
- Remove user-level model settings (chat_model_id, memory_model_id,
  embedding_model_id, max_context_load_time, language) from users table
- Merge migration 0002 into 0001, remove compatibility migrations
- Delete dead conversation/resolver.go (1177 lines, only flow/resolver.go used)
- Remove type aliases (Chat=Conversation, types_alias.go)
- Fix SQL: remove AND false stub, fix UpdateChatTitle model_id,
  reset model IDs in DeleteSettings, add preauth expiry filter,
  add ListMessages limit, remove 10 dead queries
- Extract shared handler helpers (RequireChannelIdentityID, AuthorizeBotAccess)
- Rename internal/router to internal/channel/inbound
- Fix identity confusion: remove UserID->ChannelIdentityID fallbacks
- Fix all _ = var patterns with proper error logging
- Fix error propagation: storeMessages, rescheduleJob, botContainerID
- Fix naming: ModelId->ModelID, active->is_active, Duration semantic fix
- Remove dead code: mcpService, ReplyTarget, callMCPServer, sshShellQuote,
  buildSessionMetadata, ChatRequest.Language, TriggerPayload.ChatID
- Fix code quality: errors.Is(), remove goto, CreateHuman deprecated
- Remove Enable model endpoint and user-level settings CLI commands
- Regenerate sqlc, swagger, SDK
2026-02-12 23:50:48 +08:00
BBQ 1c15eb2146 refactor(core): restructure conversation/channel/message domains and modernize deployment
- Replace chat package with conversation flow architecture
- Add channel identity avatar support (migration 0002)
- Refactor channel adapters, identities, and message routing
- Update frontend: simplify composables, modernize UI components
- Improve Docker builds with cache mounts and version metadata
- Optimize healthchecks and simplify service dependencies
2026-02-12 20:55:03 +08:00
BBQ 30281742ef merge(github/main): integrate fx dependency injection framework
Merge upstream fx refactor and adapt all services to use go.uber.org/fx
for dependency injection. Resolve conflicts in main.go, server.go,
and service constructors while preserving our domain model changes.

- Fix telegram adapter panic on shutdown (double close channel)
- Fix feishu adapter processing messages after stop
- Increase directory lookup timeout from 2s to 5s
2026-02-12 16:42:44 +08:00
BBQ ca5c6a1866 refactor(core): restructure conversation, channel and message domains
- Rename chat module to conversation with flow-based architecture
- Move channelidentities into channel/identities subpackage
- Add channel/route for routing logic
- Add message service with event hub
- Add MCP providers: container, directory, schedule
- Refactor Feishu/Telegram adapters with directory and stream support
- Add platform management page and channel badges in web UI
- Update database schema for conversations, messages and channel routes
- Add @memoh/shared package for cross-package type definitions
2026-02-12 15:34:40 +08:00