mirror of
https://github.com/chenhg5/cc-connect.git
synced 2026-10-26 01:50:40 +08:00
fix(cron): validate session_key in cron add to prevent silent runtime failures (#126)
When creating a cron job via `cron add`, if no session_key was provided (neither via --session-key flag nor CC_SESSION_KEY env), the job was created with an empty session_key. At runtime, ExecuteCronJob would fail silently because it couldn't determine the target platform from an empty session key. Add server-side validation and auto-detection in handleCronAdd: - If session_key is empty, attempt to auto-detect from the engine's active interactive sessions (works when exactly one session exists) - If auto-detection fails, return a clear error to the client Add Engine.ActiveSessionKeys() helper method to expose active session keys for the auto-detection logic. Uses platform != nil check (instead of agent session alive check) so sessions are discoverable even before an agent process is started.
This commit is contained in:
2 files changed
+33
-1
No files matched your search
+20
-1
@@ -240,10 +240,29 @@ func (s *APIServer) handleCronAdd(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// Resolve session_key: use provided, or auto-detect from active sessions
|
||||
sessionKey := req.SessionKey
|
||||
if sessionKey == "" {
|
||||
s.mu.RLock()
|
||||
engine := s.engines[project]
|
||||
s.mu.RUnlock()
|
||||
if engine != nil {
|
||||
keys := engine.ActiveSessionKeys()
|
||||
if len(keys) == 1 {
|
||||
sessionKey = keys[0]
|
||||
slog.Debug("auto-detected session_key for cron job", "session_key", sessionKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
if sessionKey == "" {
|
||||
http.Error(w, "session_key is required: set CC_SESSION_KEY env, pass --session-key, or ensure exactly one active session exists", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
job := &CronJob{
|
||||
ID: GenerateCronID(),
|
||||
Project: project,
|
||||
SessionKey: req.SessionKey,
|
||||
SessionKey: sessionKey,
|
||||
CronExpr: req.CronExpr,
|
||||
Prompt: req.Prompt,
|
||||
Exec: req.Exec,
|
||||
|
||||
@@ -533,6 +533,19 @@ func (e *Engine) ProjectName() string {
|
||||
return e.name
|
||||
}
|
||||
|
||||
// ActiveSessionKeys returns the session keys of all active interactive sessions.
|
||||
func (e *Engine) ActiveSessionKeys() []string {
|
||||
e.interactiveMu.Lock()
|
||||
defer e.interactiveMu.Unlock()
|
||||
var keys []string
|
||||
for key, state := range e.interactiveStates {
|
||||
if state.platform != nil {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
// ExecuteCronJob runs a cron job by injecting a synthetic message into the engine.
|
||||
// It finds the platform that owns the session key, reconstructs a reply context,
|
||||
// and processes the message as if the user sent it.
|
||||
|
||||
Reference in new issue
Block a user