Commit Graph
555 Commits
Author SHA1 Message Date
Claude 51767f2c19 docs: remove useless doc 2026-03-30 14:08:30 +08:00
cg33 886417166b Merge pull request #356 from chenhg5/feature/add_web_admin_v2
feat: add web admin dashboard with /web install command
2026-03-30 14:02:38 +08:00
Claude 48ff7d3094 fix(security): harden web admin static serving and API responses
- Mask bridge token in /api/v1/status (return token_set bool instead
  of the raw secret to avoid credential leakage)
- Add path traversal guard in withStaticFallback to ensure resolved
  file paths stay within the webDistDir boundary
- Stop stripping zero-value TOML lines in formatTOML — values like
  `quiet = false` or `port = 0` may be intentionally set by the user
2026-03-30 13:56:01 +08:00
Claude 454c8cdbea fix(ci): regenerate go.sum with proxy.golang.org checksums
Local Chinese Go mirror produced different checksum for BurntSushi/toml.
Regenerated go.sum using proxy.golang.org to match CI environment.

Made-with: Cursor
2026-03-30 12:32:01 +08:00
Claude 5f81ec49c2 merge: resolve conflicts with main branch
Merge github/main into feature/add_web_admin_v2.
- Go backend files auto-merged cleanly
- All web/ conflicts resolved by keeping feature branch version
  (feature branch has the latest, most complete web admin)
- Remove Logs.tsx brought in from main (no backend endpoint)
- Fix go.sum checksum for BurntSushi/toml

Made-with: Cursor
2026-03-30 11:54:58 +08:00
Claude 7461a64c60 feat: add /web command for one-click web admin install and npm publish config
- Add /web install|upgrade|status|uninstall slash command (privileged)
- Auto-install cc-connect-web via npm into ~/.cc-connect/web/
- Auto-configure [bridge] and [management] in config.toml with random tokens
- Management server serves SPA static files from dist/ with fallback to index.html
- Add config.EnableWebAdmin() for atomic bridge+management setup
- Add core/web_manager.go with npm registry integration
- Prepare web/package.json for npm publish as cc-connect-web (files: dist/)
- Add i18n translations for all /web messages (en, zh, zh-TW, ja, es)

Made-with: Cursor
2026-03-29 09:59:06 +08:00
Claude f479f6e370 test(codex): fix flaky stdin capture wait in multiline Send test
waitForFileContent returned on first successful open of the file; the
fake codex script uses `cat > file`, which can expose an empty file
briefly. Poll until contents equal the expected prompt so -cover and
CI do not race.
2026-03-28 21:06:58 +08:00
Claude be13a75406 fix(core): wait for old session to close when recycling
When a session mismatch is detected (e.g., after /new or /switch), the
old agent session was closed asynchronously via closeAgentSessionAsync().
The new session started immediately without waiting for the old one to
fully terminate, causing both agents to potentially output simultaneously
and produce duplicate responses.

Fix: Change async close to synchronous close in session recycling path.
This ensures the old agent process is fully terminated before starting
a new one. The closeAgentSessionWithTimeout() has a 10s timeout to
prevent indefinite blocking.

Root cause analysis:
- getOrCreateInteractiveStateWith() detected session mismatch
- markStopped() was called, but event loop might be mid-processing
- closeAgentSessionAsync() ran in goroutine, new session started
- Old agent continued outputting until Close() completed
- User received two similar responses from two different agents

Fixes #327

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 10:13:28 +00:00
Claude aaabb324fa test(acp): skip Cursor ACP handshake when CI is set
GitHub Actions sets CI; the integration test needs a local agent and
login and can hit its 90s timeout under load or without credentials.
Align with agent/cursor model tests that skip real CLI in CI.
2026-03-28 10:07:34 +08:00
Claude 160acc241f fix: satisfy staticcheck ST1005 for error string formatting
Lowercase fmt.Errorf prefixes in daemon/update CLI paths and collapse
systemd manager error to a single line without trailing punctuation.
</think>

mcp_GitKraken_git_push
2026-03-28 08:37:19 +08:00
Claude e0e2be4e31 fix(core): 出站限流补全、工具结果展示与 i18n 收紧
- waitOutgoing/sendWithError:重启通知、SendToSession(含图片/文件)、权限与 AskQuestion 内联按钮路径纳入出站令牌桶

- EventResult 分块与 channelClosed 收尾使用 sendWithError,首包失败即停止发送

- ProgressStyleProvider 且 progress_style=legacy 时不再单独推送 EventToolResult 聊天消息(compact/card 仍走 writer)

- 工具结果 fallback 标签改为 MsgKey,补全日/西/繁中翻译

- config.example.toml:说明小数 max_per_second 时 burst 取 ceil

- 修复 processInteractiveEvents 测试参数;新增 SuppressStandaloneToolResultEvent 单测

- fix(codex): 假 codex 脚本用 stdin 读 prompt,适配 --json -
2026-03-28 00:42:35 +08:00
Claude 5054a365bc feat(web): add global settings editor and dashboard improvements
- Add GET/PATCH /api/v1/settings endpoint for global config
- Add GlobalSettings component with editable sections: general (language,
  quiet, attachment_send, idle_timeout), display (thinking/tool max len),
  stream preview, rate limit, and log level
- Integrate global settings into System page with collapsible raw config
- Add "View All" link to Recent Sessions on Dashboard
- Add i18n translations for all global settings (en, zh, zh-TW, ja, es)

Made-with: Cursor
2026-03-28 00:19:39 +08:00
Jerry b56865fb06 feat(feishu): add configurable progress styles (compact/card) to reduce message spam
* feat(feishu): add compact progress style for thinking/tool updates

* feat(feishu): add card-style streaming progress updates
2026-03-28 00:16:13 +08:00
Max Qian d7bed29801 feat(core): add outgoing message rate limiting per platform 2026-03-27 23:59:11 +08:00
Deeka WongandDeeka Wong 1225b7ee18 feat(claudecode): add auto permission mode
Co-authored-by: Deeka Wong <8337659+huangdijia@users.noreply.github.com>
2026-03-27 23:42:53 +08:00
Jerry 5639e863d5 fix(core): route workspace model changes through session context 2026-03-27 23:31:08 +08:00
devnu11 2a8c8d3a4a fix(codex): preserve multiline prompts on resume 2026-03-27 23:20:16 +08:00
xxb 526f52e5fc fix(codex): force kill session process group on stop (#340)
* fix(codex): force kill session process group on stop

* fix(codex): kill all active session processes on stop

* fix(core): stop stale event loops on stop
2026-03-27 23:11:16 +08:00
Buqian Zheng 1104739c90 feat(telegram): migrate to go-telegram/bot and add forum topic support (#321)
* feat(telegram): migrate to go-telegram/bot and add forum topic support

Migrate the Telegram platform from the unmaintained go-telegram-bot-api/v5
(last release 2021) to go-telegram/bot v1.20.0, which is actively maintained
and supports the full Telegram Bot API including forum topics.

Key changes:

- **Library migration**: Replace go-telegram-bot-api/v5 with go-telegram/bot.
  Redesign the telegramBot interface around the new library's typed API methods
  (SendMessage, SendPhoto, EditMessageText, etc.) instead of the old generic
  Send/Request pattern. The *bot.Bot type satisfies the interface directly.

- **Forum topic support**: Add threadID to replyContext and session key.
  Messages in forum groups (IsForum=true) now include the MessageThreadID
  in the session key (telegram:{chatID}:{threadID}:{userID}), giving each
  topic its own independent agent session. All send methods propagate
  MessageThreadID so replies land in the correct topic. Non-forum groups
  and private chats are unaffected.

- **Per-topic workspace binding**: Add ChannelKey field to core.Message so
  platforms can provide an explicit channel identifier for workspace binding.
  Telegram sets this to "chatID:threadID" for forum topics, enabling
  multi-workspace mode to bind different topics to different project
  directories. Add effectiveChannelID/effectiveWorkspaceChannelKey helpers
  and update all workspace resolution call sites in the engine.

- **Skill command registration fix**: GetAllCommands now respects
  disabled_commands for skills, matching the existing behavior for
  built-in commands. This prevents disabled skills from being registered
  as Telegram bot menu commands.

- **Connection management**: Simplify the reconnect architecture.
  bot.New() handles initial validation, bot.Start(ctx) manages long
  polling internally. Remove the stale bot detection (generation
  comparison in handlers) since the new library's blocking Start()
  ensures handlers are never called from a superseded bot instance.

Signed-off-by: Buqian Zheng <zhengbuqian@gmail.com>

* fix: resolve lint errors exposed by engine.go and telegram_test.go changes

- Remove unused assignment to `s` in cmdNew (SA4006)
- Remove unused stubBotFactory and failingBotFactory helpers in telegram tests

Signed-off-by: Buqian Zheng <zhengbuqian@gmail.com>

---------

Signed-off-by: Buqian Zheng <zhengbuqian@gmail.com>
2026-03-27 23:01:33 +08:00
Claude 5a47573ec3 feat(web): add work_dir/agent_type to project creation and expand settings
- Project creation wizard now requires work_dir (working directory) and
  allows selecting agent_type (claudecode, codex, gemini, cursor, etc.)
- work_dir and agent_type are passed through QR setup (feishu/weixin)
  and manual platform form creation paths
- Project settings page reorganized into three sections:
  - Agent: work_dir, permission mode (default/acceptEdits/plan/yolo/dontAsk)
  - General: quiet, context indicator toggle, language, admin_from,
    disabled commands
  - Platform access control: per-platform allow_from editing
- Backend: GET /projects/{name} now returns work_dir, agent_mode,
  show_context_indicator, and platform_configs with allow_from
- Backend: PATCH /projects/{name} accepts and persists work_dir, mode,
  show_context_indicator, and platform_allow_from to config.toml
- config.AddPlatformToProject accepts workDir/agentType for new projects
- SaveProjectSettings refactored to use ProjectSettingsUpdate struct
- Added GetProjectConfigDetails to read extended config from TOML
- i18n: all 5 languages updated with new translation keys

Made-with: Cursor
2026-03-27 10:43:07 +08:00
Jerry b04ece2dd7 fix(core): normalize interactive session key lookup in multi-workspace mode (#267)
* fix(core): use interactive key for status card and SendToSession lookups in multi-workspace

* fix(core): remove unused new session assignment
2026-03-27 09:36:31 +08:00
Claude a6f6e720f7 feat(web): improve UI/UX, cron editor, config persistence, and theme consistency
- Remove bridge navigation and page (unused)
- Dashboard projects: grid layout (1/2/3 cols) instead of single column list
- System config: display raw TOML from config file instead of JSON summary
- Remove logs page (no backend endpoint)
- Cron page: grid layout, click-to-edit, friendly schedule dropdown,
  session key dropdown, mutually exclusive prompt/exec task type toggle
- Move language/theme/logout controls from sidebar to right header
- Unify accent color: use CSS variables with RGB format for proper
  Tailwind opacity support; light mode uses darker green (#16a34a),
  dark mode keeps neon green (#42ff9c)
- Fix Badge info variant from blue to accent green
- Align sidebar/header heights (both h-14)
- Add footer with copyright, version number, and GitHub link
- Fix project settings PATCH: persist quiet/language/admin_from/
  disabled_commands to config.toml via new SaveProjectSettings()
- Return admin_from and disabled_commands in project GET response
- Add GetDisabledCommands() to Engine for settings readback
- Backend: add PATCH support to cron job endpoint for editing
- Backend: /config endpoint returns raw TOML file content

Made-with: Cursor
2026-03-27 09:32:22 +08:00
Claude d928bb20dc feat(web): add project deletion, grid chat layout, and fix bridge WebSocket
- Add DELETE /api/v1/projects/{name} API with config.RemoveProject()
  using callback pattern to keep core/ free of config/ imports
- Move delete button from project list to project detail Settings tab
  under a "Danger Zone" section with confirmation dialog
- Wait for service recovery after restart before navigating to avoid
  empty project list
- Change Chat list from single-column IM style to responsive grid
  layout (1/2/3 cols) matching the project list design
- Fix bridge WebSocket URL to use current page host:port through the
  proxy instead of directly connecting to bridge port
- Add i18n for delete/danger zone across all 5 languages

Made-with: Cursor
2026-03-26 21:23:46 +08:00
Claude ea2033b0fb fix: WeChat QR setup polling, restart API, and TOML config formatting
- Fix WeChat QR polling stuck in "waiting for scan" caused by React 18
  StrictMode double-mount leaving cancelledRef as true; reset refs at
  flow start and inline polling loop to avoid stale closure issues
- Increase iLink API poll timeouts (37s context, 40s HTTP client) and
  Vite proxy timeout (45s) to match long-poll behavior
- Add debug logging to WeChat QR begin/poll handlers for troubleshooting
- Fix restart API returning 400 on empty body; make JSON body optional
- Add restart button to platform setup completion screen with i18n
- Add TOML config formatter: insert blank lines between sections, strip
  zero-value keys and empty sections for cleaner config output

Made-with: Cursor
2026-03-26 20:50:22 +08:00
cg33andClaude 9ca371e1f7 feat(wecom): 企业微信 HTTP 回调支持接收文件并交给 Agent (#330)
* feat(wecom): handle inbound file messages over HTTP callback

Parse MsgType=file (FileName + MediaId), download via media/get API,
and forward as core.FileAttachment for agents. Add MIME inference helper
and unit tests. Document inbound capabilities in config.example.toml.

WebSocket AI bot mode unchanged; file receive there depends on WeChat policy.

* chore(wecom): add Info/Warn logs for callback diagnostics

Log every POST (size, query flags), parsed msg_type/msg_id/from_user,
duplicate/old/allow_from drops, unsupported types at Warn, and Debug
preview of decrypted XML (truncated). Helps trace missing file pushes.

* feat(wecom-ws): receive image, file, mixed and quote media over AI bot WebSocket

Parse msgtype image/file/mixed and quote (text, voice, image, file, mixed)
per WeCom smart-bot protocol. Download encrypted media from signed URLs
and decrypt with AES-256-CBC (IV = first 16 bytes of base64 key), matching
@wecom/aibot-node-sdk. Voice accepts both content and legacy text fields.

Adds wsCollectInboundParts, deliverWSMediaInbound, unit tests for collect,
Content-Disposition parsing, and round-trip decryption.

* fix(wecom-ws): handle file in mixed payloads and normalize aeskey decoding

- Collect file items inside mixed.msg_item and merge top-level file/image
  when msgtype is file/image but a non-empty mixed block is also present.
- decodeWeComAESKey: trim whitespace, URL-safe base64, padding, optional hex.
- Add regression tests for mixed+file and aeskey variants.

* fix: satisfy golangci-lint (gosimple, staticcheck)

- wecom: use := for walkMixed/walkQuote closures (S1021).
- engine: drop unused assignment from sessions.NewSession in cmdNew (SA4006).

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-26 14:51:28 +08:00
Claude aef8cdade1 feat(web): redesign Chat page with slash commands, session drawer, and fix bridge permission handling
- Redesign Sessions → Chat: each project is a chat entry (IM-style)
- Add CommandPalette with all slash commands grouped by category
- Add SessionDrawer (right slide-out panel via /list command)
- Auto-load latest session when entering a project chat
- Fix bridge handleCardAction to properly dispatch perm:, askq:, cmd: actions as messages
- Filter incoming bridge messages by session_key to prevent session mixing
- Add chat/cmd i18n translations for all 5 languages
- Update nav, routing, and header for Chat

Made-with: Cursor
2026-03-26 14:04:04 +08:00
Claude 44b6ee4edb feat(web): add manual platform config forms with full i18n support
- Add generic AddPlatformToProject API (POST /projects/{name}/add-platform)
  that persists any platform type + options to config.toml, creating the
  project automatically if it doesn't exist.

- Add PlatformManualForm component with field metadata for 8 non-QR
  platforms (Telegram, Discord, Slack, DingTalk, WeChat Work, QQ,
  QQ Bot, LINE), supporting password toggle, required validation,
  and collapsible advanced options.

- Integrate manual forms into both the project creation wizard and
  the project detail "Add platform" dialog, replacing the previous
  "edit config.toml" fallback.

- Add i18n translations for all 28 platform field labels and hints
  across all 5 locales (EN/ZH/ZH-TW/JA/ES).

Made-with: Cursor
2026-03-25 21:34:17 +08:00
xxb 6d8bf93e4c fix: harden Discord session routing and remove implicit continue bridge (#322)
* fix(discord): dedup duplicate interaction events

* fix(core): remove implicit continue bridge

* fix(discord): avoid empty button reply references
2026-03-25 14:31:27 +08:00
cg33andClaude Opus 4.6 b5ae9444e2 feat: add web admin dashboard for cc-connect instance management (#316)
* feat(web): add web admin dashboard (React + Tailwind + TypeScript)

Full-featured management UI for CC-Connect instances:
- Token-based auth, dark/light/system theme, i18n (EN/ZH/ZH-TW/JA/ES)
- Dashboard with system status, project overview
- Project management with providers, heartbeat, settings tabs
- Session list and chat interface with Markdown rendering
- Cron job management (create/delete)
- Bridge adapter viewer
- System config viewer, logs, restart/reload controls
- All endpoints aligned with docs/management-api.md

Made-with: Cursor

* feat(web): improve session UI, markdown rendering, and API richness

- Enrich session list/detail API with live status, last_message preview,
  agent_type, platform, user metadata, and timestamps
- Add SessionKeyMap() helper to core/session.go for ID-to-key mapping
- Redesign SessionList as responsive grid layout with project filtering,
  time-ago display, and last message preview
- Upgrade markdown rendering: rehype-highlight for syntax highlighting,
  @tailwindcss/typography for proper prose styling, copy-to-clipboard on
  code blocks, GitHub light/dark themes
- Show live/offline session status; disable message input for non-live sessions
- Update management-api.md to document new session fields
- Remove node_modules from git tracking and add to .gitignore

Made-with: Cursor

* chore: add .vite/ to .gitignore

Made-with: Cursor

* fix(opencode): add warn logs when sqlite3 CLI is missing or query fails

The /list command silently showed 0 messages when sqlite3 was not installed
or the DB query failed. Now logs a warning so operators can diagnose the
issue. Fixes #318.

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-25 11:31:11 +08:00
cg33andClaude Opus 4.6 2e9d75c231 fix(opencode): add warn logs when sqlite3 CLI is missing (#319)
* feat(web): add web admin dashboard (React + Tailwind + TypeScript)

Full-featured management UI for CC-Connect instances:
- Token-based auth, dark/light/system theme, i18n (EN/ZH/ZH-TW/JA/ES)
- Dashboard with system status, project overview
- Project management with providers, heartbeat, settings tabs
- Session list and chat interface with Markdown rendering
- Cron job management (create/delete)
- Bridge adapter viewer
- System config viewer, logs, restart/reload controls
- All endpoints aligned with docs/management-api.md

Made-with: Cursor

* feat(web): improve session UI, markdown rendering, and API richness

- Enrich session list/detail API with live status, last_message preview,
  agent_type, platform, user metadata, and timestamps
- Add SessionKeyMap() helper to core/session.go for ID-to-key mapping
- Redesign SessionList as responsive grid layout with project filtering,
  time-ago display, and last message preview
- Upgrade markdown rendering: rehype-highlight for syntax highlighting,
  @tailwindcss/typography for proper prose styling, copy-to-clipboard on
  code blocks, GitHub light/dark themes
- Show live/offline session status; disable message input for non-live sessions
- Update management-api.md to document new session fields
- Remove node_modules from git tracking and add to .gitignore

Made-with: Cursor

* chore: add .vite/ to .gitignore

Made-with: Cursor

* fix(opencode): add warn logs when sqlite3 CLI is missing or query fails

The /list command silently showed 0 messages when sqlite3 was not installed
or the DB query failed. Now logs a warning so operators can diagnose the
issue. Fixes #318.

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-25 11:30:53 +08:00
Claude 607bdae273 feat(web): add QR-based platform setup and improve project management
- Add backend setup API endpoints for Feishu and Weixin QR onboarding
  flow (/api/v1/setup/{feishu,weixin}/{begin,poll,save}), proxying
  external registration APIs and persisting credentials via existing
  config.EnsureProjectWith* + SavePlatformCredentials functions.

- Add PlatformSetupQR React component with full QR scan lifecycle:
  idle → scanning → scanned → saving → completed, with retry on
  expiry/error.

- Restore "Add project" button on project list with a multi-step
  wizard (name → platform selection → QR or manual setup).

- Expand "Add platform" dialog in project detail to support all 10
  platform types (Feishu, WeChat, Telegram, Discord, Slack, DingTalk,
  WeChat Work, QQ, QQ Bot, LINE), with QR flow for Feishu/WeChat and
  manual config guidance for others.

- Add responsive font scaling in index.css (17px at 1536px, 18px at
  1920px, 20px at 2560px) for better readability on large screens.

- Add i18n keys for setup flow in all 5 locales (EN/ZH/ZH-TW/JA/ES).

Made-with: Cursor
2026-03-25 11:15:58 +08:00
Claude ba0a89dc79 fix(opencode): add warn logs when sqlite3 CLI is missing or query fails
The /list command silently showed 0 messages when sqlite3 was not installed
or the DB query failed. Now logs a warning so operators can diagnose the
issue. Fixes #318.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 02:01:44 +00:00
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 57ffaa73e1 chore: add .vite/ to .gitignore
Made-with: Cursor
2026-03-25 00:54:23 +08:00
Claude 0e11e7c159 feat(web): improve session UI, markdown rendering, and API richness
- Enrich session list/detail API with live status, last_message preview,
  agent_type, platform, user metadata, and timestamps
- Add SessionKeyMap() helper to core/session.go for ID-to-key mapping
- Redesign SessionList as responsive grid layout with project filtering,
  time-ago display, and last message preview
- Upgrade markdown rendering: rehype-highlight for syntax highlighting,
  @tailwindcss/typography for proper prose styling, copy-to-clipboard on
  code blocks, GitHub light/dark themes
- Show live/offline session status; disable message input for non-live sessions
- Update management-api.md to document new session fields
- Remove node_modules from git tracking and add to .gitignore

Made-with: Cursor
2026-03-25 00:54:04 +08:00
Claude dabb410092 feat(web): add web admin dashboard (React + Tailwind + TypeScript)
Full-featured management UI for CC-Connect instances:
- Token-based auth, dark/light/system theme, i18n (EN/ZH/ZH-TW/JA/ES)
- Dashboard with system status, project overview
- Project management with providers, heartbeat, settings tabs
- Session list and chat interface with Markdown rendering
- Cron job management (create/delete)
- Bridge adapter viewer
- System config viewer, logs, restart/reload controls
- All endpoints aligned with docs/management-api.md

Made-with: Cursor
2026-03-24 23:58:12 +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