Commit Graph
520 Commits
Author SHA1 Message Date
xxb a44b375bce fix(core): exact-resume saved session on workspace reconnect (#315) 2026-03-25 06:30:30 +08:00
ConverSun 3a0ab9dd51 fix(feishu): fall back to post format when markdown has >5 tables (#290)
Feishu interactive cards support at most 5 table components.
When the agent response contains more than 5 markdown tables,
buildReplyContent now falls back to post (md tag) format instead
of card format, preventing API error 11310 (card table number
over limit).

Add countMarkdownTables helper and corresponding tests.
2026-03-25 06:01:16 +08:00
Claude e64aa04813 Merge github/main into main (sync Discord file send + cron job details) 2026-03-24 23:15:20 +08:00
buddhism5080andClaude Code 40900b1aa2 feat(discord): 支持通过 bot 给用户发送文件 (#307)
Implement Discord FileSender so cc-connect can deliver generated files through bot replies and slash-command interactions.

Co-authored-by: Claude Code <noreply@anthropic.com>
2026-03-24 17:31:09 +08:00
Claude e065b6d22f feat(integration-tests): add integration test suite for real agent sessions
Add a new integration test suite that verifies real agent (Claude Code, Codex,
Cursor, Gemini, OpenCode) interactions with a mock platform. Tests are gated
by //go:build integration tag so they're excluded from normal CI.

core/engine.go:
- Add public ReceiveMessage(p, msg) method to allow test callers to
  inject messages into the engine

tests/integration/agent_integration_test.go:
- mockPlatform implementing core.Platform interface for test verification
- agentPool for reusing agent instances across tests
- Session tests: new session, /list, /switch, /stop, /new context clear, /history
- Agent tests: claude code, codex, cursor, gemini (skip if quota), opencode (skip if no gitlab auth)
- Command tests: /shell (skip if admin_from not set), /provider list
- i18n: /lang zh language switch
- Concurrency: session isolation, long text chunking, empty message handling

docs/plans/2026-03-24-integration-tests.md:
- Test plan listing all implemented and planned integration test cases

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 15:56:18 +08:00
术士木星andClaude Opus 4.6 38ece2a2d2 feat(cron): add command to show job details
Add new CLI command `cc-connect cron info <id>` that displays full JSON
details of a scheduled task. This helps users inspect all configuration
fields of a cron job that aren't visible in the compact `cron list` output.

Changes:
- Add `/cron/info` API endpoint in core/api.go
- Add `runCronInfo` CLI handler in cmd/cc-connect/cron.go
- Update help text to include the new command

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 15:30:25 +08:00
Claude 2700b5b027 Merge remote-tracking branch 'github/main' (sync merged PRs) 2026-03-24 14:19:13 +08:00
0a2e860b56 fix: clear old session state in /new command to prevent stale resume (#248)
* fix: require explicit session key when sending attachments with multiple sessions

When cc-connect send --image or --file is called without an explicit
--session flag and there are multiple active sessions, the code would
arbitrarily pick the first session from a map (non-deterministic order).
This could cause attachments to be sent to the wrong chat.

Now returns an error when multiple sessions exist and no session key is
specified for attachment sends. Also adds debug logging to Telegram SendImage
to aid future diagnosis.

Fixes #242

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

* fix: clear AgentSessionID on old session in /new command

When /new is invoked, the old session's AgentSessionID was not being
cleared. This could cause the old session to be resumed on the next
message if GetOrCreateActive returned it instead of the newly created
session.

The fix clears the old session's AgentSessionID and clears its history
before creating a new session, similar to how cmdSwitch handles session
transitions.

Fixes #238

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

---------

Co-authored-by: Dev Claude <dev@cc-connect.ai>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 14:17:06 +08:00
cg33andClaude 41cfde7663 fix(slack): pass file uploads to agent (fixes #292) (#296)
* fix(codex): avoid closing events channel before readLoop exits

Close() previously closed cs.events after an 8s wait even when wg.Wait
had not finished, while readLoop could still send in flushPendingAsText
(turn.completed), causing "panic: send on closed channel" after /stop
then /new. Defer channel close until readLoop completes.

Fixes https://github.com/chenhg5/cc-connect/issues/281

* fix(slack): pass non-image file uploads to agent as FileAttachment

- Map PDF/text and other non-audio/non-image Slack shares to core.FileAttachment
  so the engine persists them and has_files is true for the agent.
- Parse files from app_mention raw inner JSON (slack-go omits Files on AppMentionEvent).
- Allow app_mention with only attachments and empty stripped text.

Fixes #292

Made-with: Cursor

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-24 14:16:30 +08:00
cg33andClaude dc8808ea1a fix(engine): /new must not reuse prior Claude process (fixes #238) (#297)
* fix(codex): avoid closing events channel before readLoop exits

Close() previously closed cs.events after an 8s wait even when wg.Wait
had not finished, while readLoop could still send in flushPendingAsText
(turn.completed), causing "panic: send on closed channel" after /stop
then /new. Defer channel close until readLoop completes.

Fixes https://github.com/chenhg5/cc-connect/issues/281

* fix(engine): recycle live agent when Session clears AgentSessionID (/new)

getOrCreateInteractiveStateWith reused any alive process when wantID was empty
because the condition treated empty wantID as always compatible. After /new the
Session has no resume ID but the old Claude process still reported the previous
session — messages kept going to stale context.

Recycle when the live process has a concrete ID but the Session expects none or
a different one.

Fixes #238

Made-with: Cursor

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-24 14:16:23 +08:00
cg33andClaude 87fa8e2e4d fix(session): do not persist __continue__ as agent_session_id (fixes #255) (#298)
* fix(codex): avoid closing events channel before readLoop exits

Close() previously closed cs.events after an 8s wait even when wg.Wait
had not finished, while readLoop could still send in flushPendingAsText
(turn.completed), causing "panic: send on closed channel" after /stop
then /new. Defer channel close until readLoop completes.

Fixes https://github.com/chenhg5/cc-connect/issues/281

* fix(session): never persist ContinueSession as agent_session_id (#255)

- Reject storing the __continue__ sentinel in SetAgentSessionID; normalize in SetAgentInfo.
- Let CompareAndSetAgentSessionID overwrite a mistaken persisted sentinel with a real ID.
- Strip sentinel when loading session JSON and when saving snapshots.
- Simplify engine post-start writeback to a single CompareAndSet path.

Fixes #255

Made-with: Cursor

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-24 14:16:17 +08:00
cg33andClaude c74bd3467a fix(discord): execute slash commands when defer fails (fixes #258) (#300)
* fix(codex): avoid closing events channel before readLoop exits

Close() previously closed cs.events after an 8s wait even when wg.Wait
had not finished, while readLoop could still send in flushPendingAsText
(turn.completed), causing "panic: send on closed channel" after /stop
then /new. Defer channel close until readLoop completes.

Fixes https://github.com/chenhg5/cc-connect/issues/281

* fix(discord): run slash commands when defer interaction fails (#258)

If InteractionRespond(deferred) errors (e.g. unknown interaction), still invoke
the engine and reply via channel messages, with thread-aware replyContext for
thread channels.

Fixes #258

Made-with: Cursor

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-24 14:16:10 +08:00
cg33andClaude 1beffe3f25 fix(telegram): UTF-8-safe command menu descriptions (fixes #119) (#301)
* fix(codex): avoid closing events channel before readLoop exits

Close() previously closed cs.events after an 8s wait even when wg.Wait
had not finished, while readLoop could still send in flushPendingAsText
(turn.completed), causing "panic: send on closed channel" after /stop
then /new. Defer channel close until readLoop completes.

Fixes https://github.com/chenhg5/cc-connect/issues/281

* fix(telegram): UTF-8-safe bot command descriptions and table rows (#119)

- Truncate BotCommand.Description by runes (Telegram 256-char limit); byte
  slicing broke CJK and caused API errors.
- Make truncateForLog rune-aware for debug prefixes.
- Parse markdown table rows without byte-slicing the outer pipes.

Fixes #119

Made-with: Cursor

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-24 14:16:04 +08:00
cg33andClaude 235e54db25 fix(wecom): strip @bot mentions from inbound text (#98) (#303)
WeCom may include @robot_id in message content. Core permission matching
uses exact string comparison, so replies like "允许 @bot" failed to match.
Strip ASCII and fullwidth @ mentions for configured bot/aibot/agent IDs
before forwarding to the engine.

Fixes #98

Made-with: Cursor

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-24 14:15:57 +08:00
cg33andClaude a456ab3bd4 fix(daemon): macOS launchd do not respawn on clean exit (#153) (#304)
LaunchAgent used KeepAlive=true, so launchd restarted cc-connect after
every process exit, including graceful SIGTERM shutdown. That looked like
"stop then immediate restart" and could make tooling that waits for the
Unix API socket to disappear hang if the service respawned quickly.

Use KeepAlive with SuccessfulExit=true so only unclean exits are restarted,
matching systemd Restart=on-failure behavior.

Existing installs: re-run `cc-connect daemon install --force` to refresh
the plist.

Fixes #153

Made-with: Cursor

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-24 14:15:51 +08:00
573b1d3eb3 fix: require explicit session key when sending attachments with multiple sessions (#247)
When cc-connect send --image or --file is called without an explicit
--session flag and there are multiple active sessions, the code would
arbitrarily pick the first session from a map (non-deterministic order).
This could cause attachments to be sent to the wrong chat.

Now returns an error when multiple sessions exist and no session key is
specified for attachment sends. Also adds debug logging to Telegram SendImage
to aid future diagnosis.

Fixes #242

Co-authored-by: Dev Claude <dev@cc-connect.ai>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 14:15:43 +08:00
Claude ac79163082 fix(engine): pass replyCtx as parameter to processInteractiveEvents
Avoids race condition when cron and regular messages share the same
interactiveKey — the shared state.replyCtx was being overwritten by
concurrent goroutines, causing cron responses to be delivered to the
wrong session.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 04:14:51 +00:00
Claude c593d58e7e merge github main 2026-03-24 10:40:22 +08:00
Claude 161176e368 fix(codex): avoid closing events channel before readLoop exits
Close() previously closed cs.events after an 8s wait even when wg.Wait
had not finished, while readLoop could still send in flushPendingAsText
(turn.completed), causing "panic: send on closed channel" after /stop
then /new. Defer channel close until readLoop completes.

Fixes https://github.com/chenhg5/cc-connect/issues/281
2026-03-24 08:16:32 +08:00
cg33andClaude 66f3007f07 feat(agent): ACP (Agent Client Protocol) stdio adapter MVP
* feat(agent): add ACP stdio JSON-RPC adapter (MVP)

Implement agent/acp as an ACP client over newline-delimited JSON-RPC: initialize,
session/new or session/load, session/prompt, session/update mapping to core.Event,
and session/request_permission wired to RespondPermission.

Includes plugin_agent_acp.go (!no_acp), Makefile ALL_AGENTS entry, config example,
unit tests for transport and mapping, and AgentDoctorInfo for doctor.

Made-with: Cursor

* fix(acp): Cursor CLI compatibility — authenticate + cursor/* RPC ack

- Optional auth_method (e.g. cursor_login) triggers JSON-RPC authenticate after initialize
- initialize includes minimal clientCapabilities (fs/terminal) per Cursor ACP docs
- Acknowledge cursor/* server requests with empty result to avoid blocking tool flows
- Add integration test against ~/.local/bin/agent when present
- Document auth_method and args in config.example.toml

* fix(telegram): use Request for sendChatAction typing indicator

Telegram returns result=true for sendChatAction; BotAPI.Send unmarshals
result as Message and fails. Request only checks ok and avoids that decode.

* fix(core): surface EventToolResult in IM; extend ACP tool/thinking mapping

- Engine: handle EventToolResult in interactive loop (was silently dropped);
  compress and relay paths append tool output too. Add MsgToolResult i18n.
- ACP: stream tool_call_update for in_progress/pending; optional reasoning_*
  sessionUpdate kinds -> EventThinking; fallback hook for unknown kinds.

* fix(core): run agent Send concurrently with interactive event loop

Agents that block inside Send (e.g. ACP session/prompt) can emit
EventPermissionRequest while blocked; the engine must consume Events()
in parallel or permission prompts never reach the platform.

- processInteractiveMessageWith: async Send + pass sendDone into processInteractiveEvents
- processInteractiveEvents: select on sendDone for errors and sync at turn boundaries
- drainPendingMessages: same async Send pattern as the main path
- Add TestProcessInteractiveEvents_PermissionWhileSendBlocked regression test

* docs(acp): document OpenClaw and Copilot CLI; add display_name option

- config.example.toml: Cursor, OpenClaw (`openclaw acp`), Copilot (`copilot --acp --stdio`) examples with upstream doc links
- acp agent: optional display_name for doctor (AgentDoctorInfo)
- agent_test.go: cover default and custom display_name

* fix(core): remove ineffectual pendingSend assignments (ineffassign)

pendingSend was set to nil immediately before return or before
reassignment to nextSend; golangci-lint flags these as ineffectual.

* test(core): fix race in PermissionWhileSendBlocked under -race

The test goroutine polled stubInlineButtonPlatform.buttonRows while
processInteractiveEvents wrote them from another goroutine. Use a
permSignalInlinePlatform wrapper that signals on perm:allow via a channel
instead of racy field reads.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-24 08:03:57 +08:00
buddhism5080andClaude Opus 4.6 888cfe2828 feat(discord): 为 mode 和 reasoning 添加按钮
* feat(discord): add mode and reasoning button controls

Use Discord buttons for /mode and /reasoning, and apply Claude Code mode changes to the current session when supported.

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

* fix(discord): clean up mode labels and log button fallback errors

Remove the extra mode marker symbol, show the current mode with text instead, and include the underlying error when permission button fallbacks trigger.

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

---------

Co-authored-by: Claude Code <noreply@anthropic.com>
2026-03-24 08:03:32 +08:00
Deeka WongandDeeka Wong 288107d6bf fix(core): surface model save failures
Co-authored-by: Deeka Wong <8337659+huangdijia@users.noreply.github.com>
2026-03-24 08:03:29 +08:00
ferocknew 7bce7b12ef fix(telegram): add HTTP status code validation for file downloads
- Add file_path validation to catch empty paths
- Add HTTP status code check (resp.StatusCode != 200)
- Prevents silent failures when file downloads fail

Fixes issue where Telegram images were not being delivered to Claude Code
due to missing error handling for non-200 HTTP responses.
2026-03-24 08:03:25 +08:00
术士木星andClaude Opus 4.6 ab87b68b0b feat(cron): add cron edit command to modify job fields
* feat(cron): add `cron edit` command to modify job fields

Add new CLI command `cc-connect cron edit <id> <field> <value>` that
modifies individual fields of a scheduled task.

Features:
- Supports all editable fields: project, session_key, cron_expr, prompt,
  exec, work_dir, description, enabled, silent, mute, session_mode, timeout_mins
- Type validation: bool fields (enabled, mute) and int fields (timeout_mins)
- Read-only fields protected: id, created_at cannot be modified
- Cron expression validation before applying
- Automatic rescheduling when cron_expr or enabled changes

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

* feat(cron): add fallback reflection for string fields + comprehensive help

- Add reflection-based fallback for unknown string fields in updateJobField
- Add printCronEditUsage() with full field list, types, and examples
- Add --help/-h flag support to runCronEdit
- Update error messages to reference --help

The reflection fallback allows editing new string fields without code changes,
while type validation for known fields (bool, int) is preserved.

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

* fix(cron): protect last_run and last_error from editing

Add last_run and last_error to read-only fields list.
These are system-maintained fields that should not be manually edited.

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 08:03:21 +08:00
xxb ac34d94f05 feat(core): add shared workspace routing infrastructure
* feat(core): implement shared workspace routing and binding fallback

* fix(core): allow shared workspace commands for users

* fix(core): scope workspace bindings by platform
2026-03-24 08:03:18 +08:00
xxb aaffa0cc84 fix(core): preserve CC_SESSION_KEY in multi-workspace sessions 2026-03-24 08:03:14 +08:00
Claude 7b85a80814 fix(claudecode): omit --verbose when router_url set (stream-json safe)
router_url mode mixes non-JSON verbose output with stream-json on stdout;
disable --verbose in that configuration.

Made-with: Cursor
2026-03-23 21:55:08 +08:00
Claude 2529ee6771 docs: add ACP adapter design plan
Made-with: Cursor
2026-03-23 21:55:00 +08:00
Claude cb2371c15a feat: /dir cards, context indicator toggle, Feishu flat send option
- core: interactive /dir card (nav/act) on CardSender platforms; dirApply refactor
- core+i18n: card strings for dir history UI
- config: projects.show_context_indicator (hide [ctx: ~N%] suffix)
- feishu/lark: reply_to_trigger=false posts via Create instead of Reply
- codex: skip flush when ctx done; sync.Once on session Close
- dingtalk: stream runner reconnect loop; cancel on Stop
- go.mod: mark rsc.io/qr as direct require
2026-03-23 16:49:42 +08:00
Claude 327415d83d docs(readme): use ✅(beta) instead of 🧪 for Weixin column
Made-with: Cursor
2026-03-23 10:37:08 +08:00
Claude a30da73977 Revert "fix(discord): use rctx for slash command ReplyCtx (undefined ictx)"
This reverts commit eaaeb8a6fd.
2026-03-23 10:31:10 +08:00
Claude eaaeb8a6fd fix(discord): use rctx for slash command ReplyCtx (undefined ictx)
Made-with: Cursor
2026-03-23 10:30:34 +08:00
Claude d083bdad09 docs(readme): add platform feature snapshot matrix (stable vs beta)
Add bilingual tables after "What's New" inspired by OpenClaw China,
with legend (✅/🧪/⚠️/❌) and Weixin column marked beta-only.
Include QQ NapCat footnote and pointers to platform setup guides.
2026-03-23 10:29:15 +08:00
Leigh StillardandClaude Opus 4.6 401525931b feat: session resilience — --continue, resume recovery, context indicator
* feat: add session resilience with --continue, resume recovery, and context indicator

First connection after engine startup uses --continue to pick up the most
recent CLI session, bridging direct CLI usage and cc-connect. If resume
fails (e.g. prompt too long), automatically falls back to a fresh session.

Appends [ctx: ~XX%] to agent responses using SDK token counts, with
fallback to agent self-reported context percentage when SDK values are
unreliable.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: --continue logic bug — respect fresh session intent after first connection

Remove the startSessionID == "" condition that forced --continue even
when users explicitly requested fresh sessions (e.g. via /new). Now only
the first connection after engine startup uses --continue; subsequent
connections respect the stored session ID or "" for fresh.

Add TestFreshSessionRespectedAfterFirstConnection to verify.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(npm): correct pre-release version comparison

The isNewerOrEqual function was comparing pre-release strings
lexicographically (e.g., "beta.2" > "beta.10" due to string comparison),
causing incorrect downgrade detection. Now parses pre-release into
id and numeric parts for proper numeric comparison.

Fixes: beta version upgrade being treated as outdated and downgrading to stable.

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

* chore(npm): bump version to 1.2.2-beta.4

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

* fix: make hasConnectedOnce per-workspace so idle-reaped workspaces resume with --continue

hasConnectedOnce was engine-global, so after the first connection set it
to true, any workspace that got idle-reaped and later recreated would
skip --continue and spawn a fresh session — losing all prior context.

Move the flag into workspaceState so each workspace independently tracks
its first connection. When a workspace is reaped and GetOrCreate makes a
new one, the flag starts false again, enabling --continue on reconnection.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: fork session on resume/continue to prevent context interleaving

When cc-connect picks up a session via --continue or --resume, add
--fork-session so the platform conversation gets its own independent
context branch. This prevents history interleaving when the user is
also working in the same session from the CLI.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 08:30:19 +08:00
q107580018 fa9280b543 fix(feishu): preserve preview card finalization and silence ws heartbeat spam
* fix(feishu): preserve preview card and reduce ws heartbeat noise

* docs: document /dir usage and fix feishu reference link
2026-03-23 08:01:28 +08:00
Junyi Du e383792553 fix (discord): Discord cron thread retargeting when thread_isolation=true 2026-03-23 08:01:25 +08:00
33ca94e2f1 test(opencode): add regression tests for session list parsing (#262)
Add two focused tests to prevent regression:

1. TestOpencodeSessionEntry_Unmarshal - verifies OpenCode's JSON output
   with int64 timestamps can be unmarshaled (prevents the type mismatch
   error: cannot unmarshal number into ... of type string)

2. TestNewOpencodeSession_ContinueSessionTreatedAsFresh - verifies the
   __continue__ sentinel is not passed as literal session ID to CLI
   (regression test for PR #249)

Co-authored-by: Liujing <liujing@LiujingdeMacBook-Pro.local>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 21:38:27 +08:00
Gaoyuan-SIATandKRATSZ da7fa2b77d feat: persist /dir work directory overrides across restarts
Restore persisted /dir overrides on startup, apply them to session and heartbeat wiring, and add /dir reset plus docs so work directory changes survive restart without editing config.toml.

Made-with: Cursor

Co-authored-by: KRATSZ <KRATSZ@users.noreply.github.com>
2026-03-22 16:33:18 +08:00
Claude 0192f28661 docs(readme): add What's New (beta) section before product pitch 2026-03-22 16:02:30 +08:00
Claude 1fb24ef1ee docs: clarify personal Weixin is beta-only in README and INSTALL
State that Weixin (ilink) personal WeChat requires cc-connect@beta or
prerelease binaries; stable npm/latest release does not ship it yet.
2026-03-22 15:25:45 +08:00
Claude d50a797314 build: release v1.2.2-beta.4 — Weixin ilink, session/cron fixes, platforms
Bump npm to 1.2.2-beta.4 and document changes since v1.2.2-beta.3 in CHANGELOG.
2026-03-22 14:39:42 +08:00
Claude df14077693 fix(weixin): treat sendMessage JSON ret!=0 as failure
ilink returns HTTP 200 with business errors in the response body; parse
ret/errcode/errmsg and return an error so the engine logs platform send
failures (e.g. quota). Add sendMessageResp and a small JSON unmarshal test.
2026-03-22 14:36:29 +08:00
Claude f269c09f27 fix(weixin): harden send path, response cap, dedup, multi-voice
- Skip empty Send/Reply text to avoid empty sendMessage item_list
- Reject sendText with no items; cap ilink JSON read at 64MiB
- Dedup key adds create_time_ms and client_id; CDN encrypt_query_param dedupe per message
- Extra raw voice segments attach as voice_N.silk files when Audio already set
2026-03-22 13:04:19 +08:00
cg33andClaude 00b719d215 feat: 微信个人号(ilink)平台、扫码 setup 与 CDN 媒体 (#257)
* feat(platform): add Weixin personal (ilink) long-poll channel

Implement weixin platform against ilink bot HTTP API (getUpdates +
sendMessage), matching the OpenClaw openclaw-weixin backend.

- Text, quoted text, and voice messages with ASR text; media-only inbound
  gets a placeholder until CDN decrypt is added
- Persist get_updates_buf and per-peer context_token under data_dir
- allow_from, optional proxy/SKRouteTag, session pause on errcode -14
- ReplyContextReconstructor for cron; FormattingInstructionProvider
- Inject cc_data_dir/cc_project into all platform options for state paths
- Build tag no_weixin; Makefile + docs + config.example.toml

* feat(weixin): ilink QR setup CLI, CDN encrypt/decrypt, and Chinese docs

- Add cc-connect weixin setup/bind/new with get_bot_qrcode + get_qrcode_status flow
- Config helpers EnsureProjectWithWeixinPlatform / SaveWeixinPlatformCredentials
- Inbound CDN decrypt and outbound ImageSender/FileSender via getuploadurl
- Document weixin.md (ZH), usage guides, README/INSTALL links

Made-with: Cursor

* fix(weixin): remove unused netError type for golangci-lint

Made-with: Cursor

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-22 13:01:28 +08:00
ShawnandKevin Wang Sheng 9b2f39202d fix(feishu): always reply to original message
Previously, responses were sent as standalone messages unless
reply_in_thread was explicitly enabled in config. Now Send,
SendPreviewStart, and SendAudio always thread replies to the
original user message when messageID is available, making
conversations easier to follow.

Co-authored-by: Kevin Wang Sheng <kevinWangSheng@users.noreply.github.com>
2026-03-22 12:43:38 +08:00
Claude e99b5781c8 fix(core): replace persisted ContinueSession sentinel with real agent ID
CompareAndSetAgentSessionID only fills an empty ID; after restart the
stored sentinel __continue__ would block writing the actual session id
from the running agent. Handle that case explicitly.
2026-03-22 12:26:09 +08:00
q107580018 8a75a00df5 feat(telegram): add async startup recovery
* docs: add telegram async recovery design

* feat(telegram): add async startup recovery

* fix(telegram): resolve lint nits

* fix(core): resolve errcheck lint issues

* chore: fix launchd lint issues

* test(telegram): wrap bot api fixtures for interface
2026-03-22 12:03:30 +08:00
quabugandClaude Opus 4.6 a5085aa03d feat(discord): support @everyone/@here broadcast (#132)
* feat(discord): support @everyone/@here as bot mention via respond_to_everyone config

When multiple cc-connect bots share a Discord channel, users had to
@mention each bot individually. With respond_to_everyone = true, the bot
treats @everyone/@here as a direct mention, allowing broadcast questions
to all opted-in bots at once.

Closes #132

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

* refactor: rename config to respond_to_at_everyone_and_here

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(discord): strip @everyone/@here from message content

The pi agent treated the raw "@everyone cat or dog?" as a file path,
causing "File not found" errors. Now @everyone and @here are stripped
from the content before passing to the agent.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-22 11:33:29 +08:00
alinnbandClaude Opus 4.6 6771598e0b feat(core): add directory history for /dir command
- Add DirHistory module to track recently used directories per project
- /dir now shows history list with indices for quick navigation
- Support /dir <number> to jump to history entry
- Support /dir - to return to previous directory
- History stored in data_dir/dir_history.json
- Initial work_dir from config is automatically added to history

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 11:03:25 +08:00
quabugandClaude Opus 4.6 71a2f9b284 fix: ignore ContinueSession sentinel in non-Claude agents
* fix: ignore ContinueSession sentinel in non-Claude agents

The ContinueSession ("__continue__") sentinel was introduced in df5cc64
for the --continue bridge, but only the claudecode agent was updated to
handle it. All other agents (pi, gemini, codex, cursor, qoder, opencode,
iflow) stored the literal "__continue__" as their session/resume ID,
causing CLI failures like `No session found matching '__continue__'` and
persistent "(empty response)" replies.

The fix adds a `resumeID != core.ContinueSession` guard to each agent's
session constructor so the sentinel is treated as "" (fresh session).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(codex): remove --cd from exec resume args

The codex CLI's `exec resume` subcommand does not support --cd, causing
"unexpected argument '--cd'" errors on every resumed session. The process
working directory is already set via cmd.Dir, so --cd is unnecessary.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 10:21:11 +08:00