MCPcopy
hub / github.com/codeaashu/claude-code / useScheduledTasks

Function useScheduledTasks

src/hooks/useScheduledTasks.ts:40–127  ·  view source on GitHub ↗
({
  isLoading,
  assistantMode = false,
  setMessages,
}: Props)

Source from the content-addressed store, hash-verified

38 * so SDK/-p mode can share it — see print.ts for the headless wiring.
39 */
40export function useScheduledTasks({
41 isLoading,
42 assistantMode = false,
43 setMessages,
44}: Props): void {
45 // Latest-value ref so the scheduler's isLoading() getter doesn't capture
46 // a stale closure. The effect mounts once; isLoading changes every turn.
47 const isLoadingRef = useRef(isLoading)
48 isLoadingRef.current = isLoading
49
50 const store = useAppStateStore()
51 const setAppState = useSetAppState()
52
53 useEffect(() => {
54 // Runtime gate checked here (not at the hook call site) so the hook
55 // stays unconditionally mounted — rules-of-hooks forbid wrapping the
56 // call in a dynamic condition. getFeatureValue_CACHED_WITH_REFRESH
57 // reads from disk; the 5-min TTL fires a background refetch but the
58 // effect won't re-run on value flip (assistantMode is the only dep),
59 // so this guard alone is launch-grain. The mid-session killswitch is
60 // the isKilled option below — check() polls it every tick.
61 if (!isKairosCronEnabled()) return
62
63 // System-generated — hidden from queue preview and transcript UI.
64 // In brief mode, executeForkedSlashCommand runs as a background
65 // subagent and returns no visible messages. In normal mode,
66 // isMeta is only propagated for plain-text prompts (via
67 // processTextPrompt); slash commands like /context:fork do not
68 // forward isMeta, so their messages remain visible in the
69 // transcript. This is acceptable since normal mode is not the
70 // primary use case for scheduled tasks.
71 const enqueueForLead = (prompt: string) =>
72 enqueuePendingNotification({
73 value: prompt,
74 mode: 'prompt',
75 priority: 'later',
76 isMeta: true,
77 // Threaded through to cc_workload= in the billing-header
78 // attribution block so the API can serve cron-initiated requests
79 // at lower QoS when capacity is tight. No human is actively
80 // waiting on this response.
81 workload: WORKLOAD_CRON,
82 })
83
84 const scheduler = createCronScheduler({
85 // Missed-task surfacing (onFire fallback). Teammate crons are always
86 // session-only (durable:false) so they never appear in the missed list,
87 // which is populated from disk at scheduler startup — this path only
88 // handles team-lead durable crons.
89 onFire: enqueueForLead,
90 // Normal fires receive the full CronTask so we can route by agentId.
91 onFireTask: task => {
92 if (task.agentId) {
93 const teammate = findTeammateTaskByAgentId(
94 task.agentId,
95 store.getState().tasks,
96 )
97 if (teammate && !isTerminalTaskStatus(teammate.status)) {

Callers

nothing calls this directly

Calls 14

useAppStateStoreFunction · 0.85
useSetAppStateFunction · 0.85
isKairosCronEnabledFunction · 0.85
createCronSchedulerFunction · 0.85
isTerminalTaskStatusFunction · 0.85
logForDebuggingFunction · 0.85
removeCronTasksFunction · 0.85
formatCronFireTimeFunction · 0.85
enqueueForLeadFunction · 0.85

Tested by

no test coverage detected