Cover the remaining gap in config test coverage:
- SaveLanguage with comments
- SaveDisplayConfig with comments and unknown fields
- SaveTTSMode with comments
- Multi-project SaveActiveProvider (ensure only target project modified)
- Global provider ref SaveProviderModel (model update via provider_refs)
These tests verify the v1.3.0→v1.3.1 migration from TOML serialize
to surgical text editing doesn't silently break user config files.
Made-with: Cursor
Complete the session name mapping coverage:
- Add name mapping to relay start (CompareAndSet without name)
- Add name mapping to relay EventText handler
- These paths were the last remaining gaps from the audit
Add end-to-end tests for all three agent SessionID patterns:
- Pattern A (ACP-like): CurrentSessionID() non-empty at start
→ name mapped in startOrResumeSession
- Pattern B (claudecode/gemini/cursor-like): ID in early EventText
→ name mapped in EventText handler
- Pattern C (codex/qoder/kimi-like): ID only in EventResult
→ name mapped in EventResult handler
All three tests simulate the full /new → message → reply → verify flow.
Made-with: Cursor
Codex agent's CurrentSessionID() returns "" at startup; the thread ID
is only set after Send() triggers thread.started. The session ID reaches
the engine through EventResult (turn.completed), not EventText.
The previous fix only added name mapping in startOrResumeSession and
EventText handlers, but for codex:
- startOrResumeSession: CurrentSessionID()="" → no-op
- EventText: codex doesn't set SessionID on text events → no-op
- EventResult: was using SetAgentSessionID (unconditional) instead of
CompareAndSetAgentSessionID, and had no name mapping at all
Now all three EventResult handlers (interactive, relay, drain) use
CompareAndSet and map the pending session name on first ID binding.
Added TestSessionName_CodexLikeFlow that simulates real codex behavior:
empty CurrentSessionID at startup, ID only in EventResult.
Made-with: Cursor
When /new creates a named session, the name was stored in Session.Name
but never mapped to the agent session ID in SessionManager.sessionNames.
The name mapping only happened in the EventText handler via
CompareAndSetAgentSessionID, but that returned false because
startOrResumeSession had already set the same ID moments earlier.
Now startOrResumeSession also calls SetSessionName when it first binds
the agent session ID to a session that has a pending custom name.
Made-with: Cursor
Sessions loaded from pre-fix data had their AgentSessionIDs silently
cleared by /new and provider switches. The previous fix (PastAgentSessionIDs)
only prevented future data loss but didn't handle already-corrupted data.
Changes:
- Make legacyData unconditional in KnownAgentSessionIDs (no hasPastIDs
check that could re-enable filtering prematurely after /new)
- Persist legacyData in session snapshot via LegacyData + Version fields
- Detect partially migrated data (PastIDTracking=true but untracked
sessions exist) during load via snapshot version comparison
- Auto-clear legacyData in saveLocked only when ALL sessions have tracking
- Add end-to-end test reproducing exact user scenario: legacy data with
15 sessions → /list → /new → message → /list before reply → reply →
/list with session name verification
- Add unit test for partially migrated data detection
Made-with: Cursor
ListSessions, GetSessionHistory, DeleteSession, and patchSessionSource
all ignored the Agent.codexHome config field and only checked the
CODEX_HOME environment variable. When codex_home was set in config.toml,
StartSession correctly wrote sessions to the custom directory, but the
listing functions searched the default ~/.codex/sessions/ — making all
sessions invisible.
- Add resolveCodexHomeDir helper (explicit config > env > default)
- Thread codexHome through listCodexSessions, findSessionFile,
getSessionHistory, and patchSessionSource
- Extract CODEX_HOME from session extraEnv for post-exit patching
Made-with: Cursor
- Parse inbound `input` array with `input_text`, `input_image`,
`input_file` content parts (base64 encoded, per Weibo Open IM protocol)
- Implement `core.ImageSender` (SendImage) and `core.FileSender`
(SendFile) by encoding media as base64 in the `send_message` payload
- Add `normalizeInboundInput` to extract text/images/files from the
multi-modal input structure; input_text parts override payload.text
- Support image-only or file-only messages (no text required)
- Filter unsupported image MIME types; enforce size limits (10MB img, 5MB file)
- Extract `writeWS` helper to unify WebSocket write logic
- Add comprehensive tests: inbound image/file parsing, outbound image/file
send, MIME filtering, role filtering, interface compliance checks
Made-with: Cursor
- Rewrite SaveActiveProvider, SaveAgentModel, SaveProviderModel,
SaveLanguage, SaveDisplayConfig, SaveTTSMode to use surgical
text-level TOML editing instead of full Unmarshal→Encode cycle.
This preserves comments, unknown fields, and formatting.
- Add patchProjectAgentOption, patchTopLevelField, patchSectionField
helpers for targeted config edits.
- Extend rawProjectSpan to track [projects.agent] and
[projects.agent.options] sections.
- Add resetAllSessions to Engine; call it from management API
provider activate endpoint so sessions reset properly.
- Update docs/feishu.md: add card.action.trigger to required event
subscriptions; add FAQ for card button errors.
- Add startup log when feishu interactive card mode is enabled.
- Add tests for comment/field preservation in save functions.
Made-with: Cursor
- Update What's New to v1.3.0 stable highlights (web admin, hooks, skills, providers, weixin, feishu, new agents)
- Remove all beta/pre-release caveats from README, README.zh-CN, and INSTALL
- Add Web UI recommendation tips in Quick Start / Configure / Run sections
Made-with: Cursor
First stable 1.3 release with 555 commits since v1.2.1. Key features:
web admin UI, lifecycle event hooks, skill management page, global
provider management, cc-connect web CLI, and broad community contributions.
Made-with: Cursor
backdrop-blur on Header/Sidebar created stacking contexts that prevented
the fixed overlay from covering the top area. Using createPortal to
document.body ensures the modal escapes all ancestor overflow/stacking
constraints. Also bumped z-index to z-[9999].
Made-with: Cursor
- Add /skills route with local skills browser and recommended presets
- Backend: ListSkills/SkillDirs/AgentTypeName on Engine, skill presets API
- Provider preset cards: pin register/add buttons to card bottom
- Fix layout footer overlap by removing min-h-0 from content wrapper
- Replace logo with styled text brand, remove temporary local JSON override
- Add i18n translations for skill-related strings (en/zh/zh-TW/ja/es)
Made-with: Cursor
- Add `cc-connect web` CLI subcommand: reads config, auto-enables web
admin if needed, opens browser with token pre-filled for instant login
- Support --no-browser flag to just print URL and token
- Browser open supports macOS, Linux, Windows, and WSL
- Frontend Login page reads ?token= query param and auto-authenticates
- Add global 401 interceptor in API client: automatically logs out and
redirects to login page when token is invalid or changed
Made-with: Cursor
- Fix provider switch not taking effect: clear agent session ID on switch
to force fresh session instead of resuming with stale config
- Fix ANTHROPIC_MODEL env leak from cc-switch: explicitly set model env
when provider has custom BaseURL
- Add "clear provider" option in Feishu card for unsetting active provider
- Add debug logging for provider env vars and session startup commands
(with secret redaction via RedactEnv/RedactArgs)
- Web UI: add agent type switcher in project settings with provider
compatibility filtering and restart-required flow
- Web UI: filter global providers by agent_types when linking to project
- Web UI: fix heartbeat tab showing "running" for all projects (now shows
"not configured" when heartbeat is not enabled)
- Web UI: fix page not refreshing after agent type change + restart
- Add comprehensive integration tests for both claudecode and codex
provider switching (env vars, session args, config writing, send/receive)
- Complete i18n for all 5 languages: replyFooter, injectSender,
thinkingMessages, toolMessages and their hints
Made-with: Cursor
Add a "Import from CC-Switch" button to the web provider management
page. The backend reads the cc-switch SQLite database directly using
modernc.org/sqlite (pure Go, no CGO/sqlite3 CLI dependency), and the
frontend shows a modal with checkboxes to select which providers to
import as global providers.
- Add GET/POST /api/v1/providers/cc-switch management API endpoints
- Replace sqlite3 CLI usage with database/sql + modernc.org/sqlite
- Add CCSwitchImportModal component with i18n support (5 languages)
Made-with: Cursor
doctor_runas.go and runas_startup.go reference Unix-only symbols from
core/runas_check.go and core/runas_audit.go (both //go:build !windows)
but lacked build tags themselves, breaking Windows builds. Add
!windows tags and corresponding _windows.go stubs.
Made-with: Cursor
Provider switching was using the top-level BaseURL/Model from global
providers instead of per-agent-type overrides (Endpoints/AgentModels/
AgentModelLists). This caused agents like Codex to hit the wrong API
endpoint (e.g. /api/responses instead of /api/v1/responses), resulting
in 404 errors.
Also:
- Extract ProviderConfig.ResolveForAgent() to deduplicate override logic
- Cascade-delete provider_refs when a global provider is removed
- Purge deleted providers from running engines at runtime
- Add per-agent-type config UI for global provider form (tabbed when ≥2 agents)
- Add i18n translations for new form fields
Made-with: Cursor
- Restructure provider-presets.json (v1→v2): replace flat endpoints/
agent_models/models/agents/codex_config fields with a unified
`agents` map keyed by agent type, each containing base_url, model,
models list, and optional codex_config
- Update ProviderPreset Go struct with PresetAgentConfig and helper
methods SupportsAgent()/AgentConfig()
- Add AgentModelLists to config.ProviderConfig for per-agent model
lists; ResolveProviderRefs now resolves models per agent type
- Filter global provider linking by agent type in IM /provider add
card and executeProviderLink to prevent incompatible associations
- Fix Codex 404 caused by shengsuanyun agent_types including "codex"
with wrong base_url; remove codex from its agent_types
- Update web frontend ProviderPreset type and preset display/add logic
to use the new agents map structure
Made-with: Cursor
- Fix SaveProviderModel to look up global [[providers]] via provider_refs
when provider is not found in project inline list
- Fix RemoveProviderFromConfig to also remove provider_refs entries
- Fix project provider linking creating duplicates (remove extra addProvider)
- Remove project-level "available models" card (manage in global providers)
- Add model list editor with click-to-set-default in provider form
- Add collapsible model badges (3 for providers, 5 for presets)
- Update i18n for model editor hints (all 5 languages)
Made-with: Cursor
Star badge is now driven by the `featured` field in provider-presets.json.
Currently no preset has featured=true, so no stars are shown.
Can be toggled on per-provider remotely without code changes.
Made-with: Cursor
- Fix display_name from 省算云 to 胜算云 in provider-presets.json
- Show invite/register link in API key prompt card for preset providers
- Add MsgProviderAddInviteHint i18n key with all 5 languages
Made-with: Cursor
- Add global [[providers]] config with project-level provider_refs
- Add provider management page in web admin with preset support
- Implement card-based /provider add flow: preset selection card
with sponsor presets, API key prompt, and manual "Other" option
- Add inline button support for Telegram-style platforms
- Add remote provider-presets.json with sponsor data
- Add REST API endpoints for global providers and provider refs
- Update project detail providers tab with unified list UI
Made-with: Cursor
Quoted message prefix was prepended directly to Content, making
the first character not '/' and breaking command parsing. Move the
quoted prefix to ExtraContent which is merged after command detection.
Made-with: Cursor
Implement Weibo private message platform via the Open IM WebSocket
protocol (open-im.api.weibo.com). Supports app_id/app_secret auth,
automatic token refresh, heartbeat keep-alive, reconnect with
exponential backoff, message dedup, and chunked sending for long
messages (2000 char limit).
Includes plugin registration, build tag (no_weibo), unit tests,
setup documentation, and cross-references in all platform docs.
Made-with: Cursor
Previously done_emoji only fired when stream preview had been updated
in-place at least once, which meant quick responses never triggered
the reaction. Remove the needsDoneReaction() gate so the platform's
AddDoneReaction is always called on EventResult.
Made-with: Cursor
Remove the standalone /agentsid command and fold its output (Agent SID)
into /status. Also add work_dir to the status output so users can see
the current working directory at a glance.
Changes:
- Remove /agentsid command registration, handler, card button, help
text, and all i18n entries (MsgAgentSIDWarning, MsgBuiltinCmdAgentSID)
- Add Agent SID line to /status (both plain-text and card variants),
shown only when a session is active
- Add Work Dir line to /status output (i18n: 5 languages)
- Add MsgStatusAgentSID i18n key
Made-with: Cursor
Previously, /switch overwrote the active session's AgentSessionID,
causing the old agent session to disappear from KnownAgentSessionIDs
and thus from /list output.
Add SwitchToAgentSession() which finds an existing internal session
for the target agent session ID or creates a new one, preserving all
previous session references.
Made-with: Cursor
doctor_runas.go and runas_startup.go reference core types gated
behind //go:build !windows. Add the same constraint and provide
a stub file so Windows cross-compilation succeeds.
Made-with: Cursor
H1: Kimi readLoop — move cmd.Wait() before EventResult to prevent
out-of-order EventError after turn completion.
H2: Kimi tests — add skipUnlessKimiAvailable guard so CI without
kimi binary skips gracefully instead of failing.
H3: Claude shellJoinArgs — add comprehensive unit tests for shell
quoting (spaces, single quotes, backslashes, newlines).
M1: cli_path — document that paths with spaces are not supported.
M3: needsDoneReaction — add streaming preview tests covering
UpdateMessage trigger, discard reset, and disabled state.
M5: /agentsid — add security warning about session ID sensitivity
in the command response.
M7: i18n — localize reply_footer_remaining for ZH/ZH-TW/JA/ES;
add MsgAgentSIDWarning translations for all 5 languages.
Made-with: Cursor
- Move AIGoCode to first position (highest sponsor)
- Update AICodeMirror description: "CC users" instead of "cc-connect users"
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
H1: Prevent workspace path traversal via ../
Add resolveLocalDirPath() that validates resolved path stays under
baseDir, expands ~/... via os.UserHomeDir, rejects escaping paths.
M2: Sanitize sender_name in inject_sender header
Replace quotes with single quotes, strip newlines/CR to prevent
prompt injection via display names.
M3: Warn on unset env var placeholders in config
resolveEnvPlaceholders now logs slog.Warn when ${VAR} references
an environment variable that is not set.
M4: Validate WeCom api_base_url
Reject non-http(s) or malformed URLs at New() to prevent credential
exfiltration via misconfigured base URL.
M5: Quote systemd Environment= values
Wrap values in double quotes to handle spaces, #, and special chars
in proxy URLs and paths.
M7: Discord table detection now requires separator row
Only wrap pipe-delimited blocks that contain a markdown separator
row (| --- | --- |), reducing false positives on decorative pipes.
Made-with: Cursor
- AICodeMirror: Claude Code/Codex/Gemini CLI relay service
- AIGoCode: All-in-one Claude Code/Codex/Gemini platform
- Code0: AI model API relay for Chinese developers
- claudeapi.com: Premium direct Claude connection service
Sponsor section moved to front (after language switch), similar to cc-switch layout.
Full descriptions preserved for AICodeMirror and AIGoCode.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
H1: Prevent double-Close on concurrent cleanupInteractiveState calls
by nil'ing state.agentSession under the lock before closing.
H2: Weixin StartTyping sends typingStatusStop on ctx.Done() and on
repeat-failure exit, preventing stuck "typing" indicator.
M3: Feishu @mention resolution: downgrade PII log to Debug, HTML-escape
display names in at tags, skip ambiguous (duplicate) names.
M4: Narrow segmentStart==0 condition in EventResult to only apply when
tool messages are hidden (!e.display.ToolMessages).
M5: Log warning when cron workspace agent creation fails instead of
silently falling back to global agent.
M7: Discord file download capped at 50 MiB via io.LimitReader.
M8: Weixin getConfig now checks ret/errcode fields and returns error
on non-zero values.
Made-with: Cursor
Two race conditions fixed:
1. cleanupInteractiveState timing (main issue):
- Previously: state was deleted from interactiveStates map BEFORE
closeAgentSessionWithTimeout was called synchronously
- Problem: during the blocking close (up to 130s for Stop hooks),
the map was empty but agent session was still shutting down
- Result: concurrent requests saw conflicting state - some got
"No execution in progress" while others saw blocking behavior
- Fix: delete state from map AFTER closeAgentSessionWithTimeout
completes, with re-check to avoid deleting replaced states
2. readLoop defer leak (secondary issue):
- Previously: defer had early return on ctx.Done() that skipped
closing cs.events and cs.done channels
- Problem: if Close() timed out and called cancel(), the defer
returned early without closing channels
- Result: Close() waits forever on cs.done at line 633
- Fix: remove early return from defer, always close channels
Root cause identified in issue #595:
- Session cleanup during /stop in cleanup window created conflicting
replies ("Previous request still processing" vs "No execution in progress")
- MCP servers and Stop hook subprocesses with stdio:inherit could
block scanner.Scan() indefinitely, preventing defer cleanup
Test plan:
- go build ./... passes
- go vet ./... passes
- go test ./... passes
Fixes#595
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Weixin platform now implements core.AudioSender interface, enabling TTS
audio output for WeChat personal chat via ilink API.
- Added ConvertAudioToAMR in core/speech.go for audio conversion
- Implemented SendAudio in platform/weixin/media_outbound.go
- Converts WAV/MP3/TTS output to AMR format (Weixin voice codec)
- Uploads via CDN and sends as voice message type
Fixes#587: TTS audio was generated but silently dropped because
weixin did not implement AudioSender interface.
Test plan:
- go build ./... passes
- go test ./... passes
- Unit tests for SendAudio edge cases (empty audio, invalid context)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add skipUnlessAgentReady() that checks both CLI binary and API key
env vars (ANTHROPIC_API_KEY, OPENAI_API_KEY, etc.) before running
agent integration tests, preventing false-negative timeouts in CI
- Fix multi_workspace_shared_test.go: replace immediately-closed events
channel with buffered channel to prevent engine's processInteractiveEvents
from exiting prematurely
- Fix TestNewSessionClearsContext: adjust expectation since Claude Code
memory is workspace-scoped (persists across /new), verify session
functionality instead of memory erasure
Made-with: Cursor
High priority:
- PR #420: fix Telegram reply context lost by alias resolution —
resolveAlias now runs on user text before ExtraContent merge
- PR #567: fix message queue race — adoptPendingFromPlaceholder
copies queued messages when placeholder state is replaced
- PR #437: harden /diff command — reject targets starting with '-',
use '--' separator to prevent git option injection
- PR #560: add run_as_env dangerous variable blacklist (LD_PRELOAD,
PATH, HOME, etc.); fix doc claiming PATH is in default allowlist
Medium priority:
- PR #497: ACP permission params log level Info→Debug to prevent
sensitive data leaking; add toolInputByID cache size cap (1000)
- PR #559: observe new JSONL files start from EOF instead of offset 0,
preventing full session history replay to Slack
- PR #510: add idempotent Close() test for claude session
- PR #514: bridge ReconstructReplyCtx already has structured JSON +
backward compat; added decode helper + tests
- PR #440: add instance lock acquire/release unit tests
- PR #569: document ContinueSession behavioral change in code comments
All changes backward-compatible. Tests added for all fixes.
Made-with: Cursor
The /quiet slash command was a frequently used user-facing feature
that was accidentally removed when thinking/tool visibility was
split into separate config items. Restore it as a toggle that
flips both ThinkingMessages and ToolMessages together, persisting
the change via displaySaveFunc. Also restores /quiet in the help
card listing.
Made-with: Cursor
- Add ❤️ Sponsor section with placeholder and contact info
- Add ☕ Support the Project (donation) section
- Include WeChat Pay and Alipay QR codes
- Add Buy Me a Coffee link
- Add 🤝 Commercial Cooperation section
- Simplify donor recognition - leave username in donation message
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add "Support the Project" section with Buy Me a Coffee link
- Include WeChat Pay and Alipay QR codes
- Add donor recognition section with GitHub username request
- Update both English and Chinese READMEs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace "Open an issue" with direct contact methods
- Add email (chg80333@gmail.com) and WeChat (mongorz)
- Add Telegram/Discord community links
- Create SVG placeholder image for sponsor slot
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace blanket `!web/dist/` exception with `web/dist/*` to ignore
all generated files (assets/, index.html, favicon.svg) while keeping
`.keep` for directory preservation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Discord allows at most 100 application commands per bulk overwrite
(guild or global). The previous limit of 200 caused silent HTTP 400
failures when users had >100 commands. Now truncates at 100 and logs
the count of dropped commands.
Closes#504
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- PR #445: auto-compress skips when agent has no CompressCommand;
--max-context-tokens is now configurable via agent options instead
of being hardcoded to 900000
- PR #448: codex app-server RPC timeout cleans pending map entry;
emit() uses non-blocking send to prevent readLoop stall;
readLoop uses scanner with 10MB max line size
- PR #462: restore backward-compatible quiet config — maps to
display.thinking_messages/tool_messages when [display] not set
- PR #479: Gemini STT sends API key via x-goog-api-key header
instead of URL query param; model name is URL-escaped
- PR #489: feishu fetchQuotedMessage uses caller context instead
of context.Background; extractPostPlainText includes code_block
- PR #447/#474: SendToSessionWithAttachments uses workspace-prefix
stripping fallback matching cron/heartbeat logic
- PR #446: PATH prepend for custom commands limited to Windows only
All changes are backward-compatible; new behavior gated by config.
Tests added for quiet config, workspace prefix, Gemini header, and
feishu code_block extraction.
Made-with: Cursor
- Add ❤️ Sponsor section with placeholder for sponsors
- Add 🤝 Commercial Cooperation section for enterprise customization, consulting, and outsourcing
- Create docs/images/sponsors/ directory for sponsor logos
- Update both English and Chinese READMEs
Reference: cc-switch sponsorship model
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Revert the BurntSushi/toml checksum change — the previous update was
caused by a misconfigured local Go module proxy returning different
content than the canonical proxy.golang.org.
Made-with: Cursor
- Set state.pending BEFORE sending permission prompt so
handlePendingPermission never reads nil when the platform
callback fires immediately (fixes flaky
TestProcessInteractiveEvents_PermissionWhileSendBlocked
under -race)
- Update go.sum for BurntSushi/toml v1.6.0 checksum change
Made-with: Cursor
The --sandbox flag requires kernel v6.2+ and is unavailable on most
headless servers. The actual issue users hit ("only ls allowed") is
the Shell tool command allowlist in --trust (default) mode, which is
resolved by switching to mode = "force" (--force).
Reverts the sandbox config option; updates config.example.toml to
clearly document that default mode restricts shell to safe commands.
Made-with: Cursor
Cursor Agent CLI defaults to sandbox mode in headless environments,
limiting available tools to read-only operations (ls, etc.). Add a
configurable `sandbox` option ("enabled"/"disabled"/"") that maps to
the `--sandbox` CLI flag, allowing users to unlock full tool access
(shell, edit, write) when running via cc-connect.
Config example:
[projects.agent.options]
sandbox = "disabled"
Made-with: Cursor
- Enhanced formatTOML to also strip trailing whitespace per line,
collapse consecutive blank lines, and trim leading blank lines
- writeRawConfig now applies formatTOML before writing, so every
config save path produces consistently formatted output
- Added `cc-connect config` subcommand group:
- `config format` (alias: `fmt`) — format the config file in place
- `config example` — print annotated config example
- `config path` — print resolved config file path
- Old `config-example` subcommand kept for backwards compatibility
- Added FormatConfigFile() with TOML validation before writing
- Added tests for formatTOML and FormatConfigFile
Made-with: Cursor
pickAgentTemplateForNewProject always cloned the first project's agent
config when any project existed, ignoring the explicitly passed AgentType.
This caused the web admin "Add Project" wizard to always create projects
with the same agent type as the first project, regardless of user selection.
Fix: check opts.AgentType before falling back to cloning the first project.
Made-with: Cursor
AvailableModels now runs `<cmd> models` first and falls back to
provider-configured models and the built-in list only when the CLI
command fails or produces no output. Results are deduplicated and
sorted for stable /model output.
Co-authored-by: q107580018 <107580018@qq.com>
Made-with: Cursor
Both features are marked as Beta (v1.2.2-beta.5+). Covers /web setup
chat command, manual config.toml options, Management API endpoints,
Bridge WebSocket/REST access, authentication methods, and build tags.
Made-with: Cursor
The go:embed directive in web/embed.go requires web/dist/ to exist.
Add Node.js setup and npm build steps to lint and unit-test jobs.
Use no_web tag for smoke/regression/performance tests that don't
need web assets.
Made-with: Cursor
Replace the npm-based install/upgrade workflow with compile-time
embedding. The web/dist/ directory is now embedded directly into the
binary using go:embed and registered through core's plugin registry
pattern (web/embed.go → core.RegisterWebAssets).
- Add web/embed.go (go:build !no_web) and web/embed_stub.go
- Add core/web_assets.go as the embedded FS registry
- Add cmd/cc-connect/plugin_web.go to import the web package
- Rewrite management.go static serving to use io/fs instead of disk
- Simplify /web command to setup + status (remove install/upgrade/uninstall)
- Clean up web_manager.go (remove npm logic, keep GenerateToken)
- Update Makefile with web build target and NO_WEB/build-noweb support
- Remove .npmignore and npm publishing fields from package.json
Binary size impact: ~1MB (16M → 17M). Use `no_web` tag to exclude.
Made-with: Cursor
Discord Gateway and API connections can now be routed through an HTTP
proxy, configured via `proxy`, `proxy_username`, and `proxy_password`
options — matching the existing Telegram proxy support.
Made-with: Cursor
Images and files were saved to /tmp which is outside Gemini CLI's
workspace sandbox, causing "file not found" when the agent tried to
read them. Now saves to workDir/.cc-connect/attachments/ (consistent
with the claudecode adapter) and provides explicit paths in the prompt.
Made-with: Cursor
- 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
Local Chinese Go mirror produced different checksum for BurntSushi/toml.
Regenerated go.sum using proxy.golang.org to match CI environment.
Made-with: Cursor
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