Add cliBin and cliExtraArgs fields to the codex Agent, parsed from the
new cli_path option (e.g. cli_path = "omx" or cli_path = "omx --flag").
The binary is used for both LookPath validation and subprocess execution,
allowing users to run codex-compatible CLIs like omx through cc-connect.
Closes#545
Co-authored-by: Claude <noreply@anthropic.com>
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
- 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
- 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
* feat(core): add optional reply footer metadata
* feat(config): enable reply footer by default
* feat(codex): use runtime footer metadata from app-server
* feat(codex): resolve exec footer metadata at runtime
* feat(core): style reply footer and prefer context left
* feat(codex): use real runtime context for reply footer
* feat(core): use english left footer text
* fix(codex): use current context tokens for footer left
* fix(codex): match cli context left calculation
* test(codex): adapt footer tests to session base url arg
Codex CLI 0.118.0 deprecated the OPENAI_BASE_URL env var. When users
switch providers via /provider, the new base URL was set as an env var
but ignored by the CLI. Now pass it as `-c openai_base_url=<url>` on
each subprocess invocation so the correct endpoint is used immediately.
Closes#554
Co-authored-by: Claude <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
- fix(#348): call cleanupInteractiveState after new_per_run cron completes
to prevent orphaned Claude CLI processes accumulating over time
- fix(#378): codex CompressCommand() returns "" since /compact is not
reliably executed in exec/resume mode (may be treated as plain text)
- feat: notify user via platform message before auto-compress triggers,
including token estimate (~Xk tokens) for transparency
- fix(#384): pass --max-context-tokens 900000 to claude CLI, raising the
effective context limit from ~254K to 900K tokens
Co-authored-by: 菇菇 <gugu@gugudeMac-mini.local>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
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.
* 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
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
- 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
* 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>
- Only flip hasConnectedOnce when starting an agent for non-synthetic
messages (exclude UserID cron and heartbeat) so scheduled jobs cannot
consume the one-time ContinueSession bridge.
- Add regression tests and align Codex exec resume arg comments with
the actual --json placement.
Fixes issue #220 where the second message in a Codex session would fail
with "error: unexpected argument '--json' found" because the --json flag
was placed before the thread_id positional argument instead of after it.
The codex CLI requires the --json flag to be placed after the subcommand
and positional arguments (thread_id) for the resume command to work correctly.
Before:
codex exec resume --json --skip-git-repo-check <thread_id> <prompt>
After:
codex exec resume --skip-git-repo-check <thread_id> --json --cd <dir> <prompt>
Co-authored-by: Ubuntu <ubuntu@localhost.localdomain>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix(core): share provider model lookup and stabilize tests
* fix(tests): address PR review follow-ups
---------
Co-authored-by: Deeka Wong <8337659+huangdijia@users.noreply.github.com>
Six agent session adapters (codex, cursor, gemini, iflow, opencode,
qoder) only close the events channel when wg.Wait completes within
the 8-second timeout. If the timeout fires, the channel is left open,
which can cause consumers to block indefinitely waiting for channel
closure and prevents the engine from detecting that the session has
ended.
Move close(events) after the select block so the channel is always
closed regardless of whether the timeout fires, matching the pattern
already used by piSession.
In 6 agent session implementations (codex, opencode, qoder, iflow, cursor,
gemini), Close() unconditionally calls close(events) after an 8-second
timeout, even when the readLoop goroutine may still be running and
sending events to the channel. Due to Go's select non-determinism, the
readLoop goroutine can choose the send case over the ctx.Done() case,
causing a "send on closed channel" panic.
Move close(events) into the case where wg.Wait() succeeds (readLoop has
fully exited), and skip closing on timeout to prevent the race. This
follows the same safe pattern already used by claudeSession, where the
events channel is only closed after the readLoop goroutine has finished.
Extract SaveFilesToDisk/AppendFileRefs helpers into core package and
wire up file handling for Cursor, Codex, OpenCode, Qoder, and iFlow.
Files are saved to .cc-connect/attachments/ and paths are appended to
the prompt so each CLI can read them with its built-in tools.
Also refactors Claude Code to reuse the shared helper.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add FileAttachment type and wire up file handling across the stack so
that files sent in Feishu are downloaded and forwarded to agents.
Claude Code saves files locally for tool-based reading; Gemini passes
them as temp file references. Other agents log a warning and ignore.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Updated buffer sizes for stdout scanners across all agent sessions:
- Initial buffer size reduced from 1MB to 64KB
- Max buffer size increased from 1MB to 10MB
generated by llmgit
Co-Authored-By: Claude <noreply@anthropic.com>
Add pending message buffer to accumulate agent messages before classification.
Improve event handling with better logging and support for additional event types.
Add helper functions for text extraction and tool input processing.
Handle turn failures and flush messages appropriately for thinking/text events.
generated by llmgit
Co-Authored-By: Claude <noreply@anthropic.com>
Add patchSessionSource function to rewrite session_meta lines in Codex JSONL transcripts, changing source from "exec" to "cli" and originator to "codex_cli_rs" for CLI visibility. Includes tests for patching behavior and idempotency.
generated by llmgit
Co-Authored-By: Claude <noreply@anthropic.com>
Implement session deletion functionality across all agent implementations (claudecode, codex, cursor, gemini)
Add new /delete command with session lookup by ID/prefix
Add i18n support for delete-related messages
Update command help texts to include new delete command
Add SessionDeleter interface for agents supporting deletion
Implement core deletion logic with active session protection
generated by llmgit
Co-Authored-By: Claude <noreply@anthropic.com>
Added timeout mechanisms with logging for graceful session closure across multiple agent types (claudecode, codex, cursor, gemini, opencode, qoder). Modified engine cleanup to handle timeouts and improve logging. Sessions now timeout after 8-10 seconds with appropriate warnings/errors.
generated by llmgit
Co-Authored-By: Claude <noreply@anthropic.com>
Add context-aware select statements when sending events to prevent blocking on closed channels. Implement secure argument logging using RedactArgs to mask sensitive flags. Add atomic file writes and locks for config safety. Improve session handling with mutex protection and deduplication checks.
generated by llmgit
Co-Authored-By: Claude <noreply@anthropic.com>
Remove fixed 200-rune truncation from all agents since truncation
is now handled dynamically via /config (thinking_max_len, tool_max_len).
Affected agents: claudecode, codex, cursor, gemini, qoder
Co-Authored-By: Claude <noreply@anthropic.com>
- Added --stdin support for sending multi-line/special character messages via heredoc
generated by llmgit
Co-Authored-By: Claude <noreply@anthropic.com>
Implement context compression functionality across agents with `/compress` and `/compact` commands. Adds ContextCompressor interface, command handling in engine, and i18n messages. Supported agents implement CompressCommand() with their specific commands.
generated by llmgit
Co-Authored-By: Claude <noreply@anthropic.com>
Add model selection capabilities across all agents with:
- ModelSwitcher interface for dynamic model switching
- `/model` command to list/change models
- Default model lists for each agent
- API-based model fetching with fallback
- Session-aware model persistence
- I18n support for model messages
generated by llmgit
Co-Authored-By: Claude <noreply@anthropic.com>
Add MemoryFileProvider interface and implement in claudecode, codex, and gemini agents
Add /memory command to view/edit memory files with translations
Update help text to include new command
generated by llmgit
Co-Authored-By: Claude <noreply@anthropic.com>