{"version":3,"sources":["../src/hooks/useAmbient.ts"],"names":["useState","useRef","useEffect","fireBusEvent","useCallback"],"mappings":"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","file":"chunk-FYXTZZQD.cjs","sourcesContent":["/**\n * useAmbient — background thinking loop with live countdown state.\n *\n * Inspired by agi-diy/docs/vision.js AmbientMode class.\n * Emits `careless:ambient-fire` when ready for the app to send a prompt.\n *\n * States: idle (waiting user stop) → cooldown → ready → running → done\n */\nimport { useEffect, useRef, useState, useCallback } from 'react'\nimport { fireBusEvent } from '../lib/event-bus'\nimport type { AgentStatus } from '../types/index'\n\nexport type AmbientState = 'off' | 'idle' | 'cooldown' | 'waiting' | 'running' | 'ready' | 'done'\nexport type AmbientMode = 'standard' | 'autonomous'\n\nexport interface AmbientStatus {\n  state: AmbientState\n  mode: AmbientMode\n  iteration: number\n  maxIterations: number\n  secondsRemaining: number\n}\n\ninterface Opts {\n  enabled: boolean\n  autonomous?: boolean\n  idleThresholdMs?: number\n  cooldownMs?: number\n  maxIterations?: number\n  agentStatus: AgentStatus\n  lastQuery?: string | null\n  /** Last assistant response text — checked for [AMBIENT_DONE] completion signal. */\n  lastResponse?: string | null\n  onFire: (prompt: string, iteration: number) => Promise<void> | void\n  /** Called when the agent signals completion with [AMBIENT_DONE] or similar. */\n  onComplete?: () => void\n}\n\n/** Magic phrases the agent can use to signal autonomous completion. */\nconst COMPLETION_SIGNALS = [\n  '[AMBIENT_DONE]',\n  '[TASK_COMPLETE]',\n  '[NOTHING_MORE_TO_DO]',\n  'i\\'ve completed my exploration',\n  'nothing more to explore',\n  'task is complete',\n]\n\nfunction hasCompletionSignal(text: string | null | undefined): boolean {\n  if (!text) return false\n  const lower = text.toLowerCase()\n  return COMPLETION_SIGNALS.some(sig => lower.includes(sig.toLowerCase()))\n}\n\nexport function useAmbient(opts: Opts): AmbientStatus & { reset: () => void; trigger: () => void } {\n  const { enabled, autonomous = false, agentStatus, lastQuery, lastResponse, onFire, onComplete } = opts\n  const idleThresholdMs = opts.idleThresholdMs ?? (autonomous ? 0 : 30_000)\n  const cooldownMs = opts.cooldownMs ?? (autonomous ? 8_000 : 60_000)\n  const maxIterations = opts.maxIterations ?? (autonomous ? 100 : 3)\n\n  const [state, setState] = useState<AmbientState>(enabled ? 'idle' : 'off')\n  const [iteration, setIteration] = useState(0)\n  const [secondsRemaining, setSecondsRemaining] = useState(0)\n\n  const lastInteractionRef = useRef(Date.now())\n  const lastFireRef = useRef(0)\n  const firingRef = useRef(false)\n\n  // Record activity whenever user types or agent is busy\n  useEffect(() => {\n    if (agentStatus === 'streaming' || agentStatus === 'thinking') {\n      lastInteractionRef.current = Date.now()\n    }\n  }, [agentStatus])\n\n  useEffect(() => {\n    const handler = () => { lastInteractionRef.current = Date.now() }\n    window.addEventListener('keydown', handler)\n    window.addEventListener('mousedown', handler)\n    window.addEventListener('touchstart', handler)\n    return () => {\n      window.removeEventListener('keydown', handler)\n      window.removeEventListener('mousedown', handler)\n      window.removeEventListener('touchstart', handler)\n    }\n  }, [])\n\n  // Detect AMBIENT_DONE / completion signal in agent responses\n  useEffect(() => {\n    if (!autonomous || !lastResponse) return\n    if (hasCompletionSignal(lastResponse)) {\n      console.log('[ambient] completion signal detected — stopping autonomous loop')\n      setState('done')\n      setIteration(i => Math.max(i, maxIterations)) // prevent re-fire\n      try { onComplete?.() } catch {}\n      try { window.dispatchEvent(new CustomEvent('careless:ambient-complete', { detail: { iteration } })) } catch {}\n      fireBusEvent({ source: 'ambient', kind: 'completed', summary: `Autonomous loop complete at iter ${iteration}` })\n    }\n  }, [autonomous, lastResponse, maxIterations, onComplete, iteration])\n\n  const fire = useCallback(async () => {\n    if (firingRef.current) return\n    firingRef.current = true\n    setState('running')\n    const nextIter = iteration + 1\n    fireBusEvent({ source: 'ambient', kind: 'fired', summary: `${autonomous ? 'autonomous' : 'ambient'} iter ${nextIter}/${maxIterations}` })\n    const prompt = autonomous\n      ? (iteration === 0 && lastQuery\n          ? `[AUTONOMOUS MODE] Continue: \"${lastQuery.slice(0, 300)}\". Take action. When truly done, include [AMBIENT_DONE].`\n          : `[AUTONOMOUS iteration ${nextIter}] Continue working. [AMBIENT_DONE] when done.`)\n      : (lastQuery\n          ? `[AMBIENT] Reflect on \"${lastQuery.slice(0, 200)}\". Go deeper, find improvements.`\n          : `[AMBIENT] Think about what to do next based on current context.`)\n    try {\n      await onFire(prompt, nextIter)\n    } catch (e) { console.error('[ambient] fire error', e) }\n    finally {\n      firingRef.current = false\n      lastFireRef.current = Date.now()\n      setIteration(nextIter)\n      if (nextIter >= maxIterations) setState('done')\n    }\n  }, [iteration, autonomous, lastQuery, onFire, maxIterations])\n\n  useEffect(() => {\n    if (!enabled) { setState('off'); return }\n    if (state === 'done') return\n    const interval = setInterval(() => {\n      if (agentStatus === 'streaming' || agentStatus === 'thinking') {\n        setState('waiting')\n        setSecondsRemaining(0)\n        return\n      }\n      const idleFor = Date.now() - lastInteractionRef.current\n      const sinceFire = Date.now() - lastFireRef.current\n      if (iteration >= maxIterations) { setState('done'); return }\n      if (!autonomous && idleFor < idleThresholdMs) {\n        setState('idle')\n        setSecondsRemaining(Math.ceil((idleThresholdMs - idleFor) / 1000))\n        return\n      }\n      if (sinceFire < cooldownMs) {\n        setState('cooldown')\n        setSecondsRemaining(Math.ceil((cooldownMs - sinceFire) / 1000))\n        return\n      }\n      setState('ready')\n      setSecondsRemaining(0)\n      fire()\n    }, 500)\n    return () => clearInterval(interval)\n  }, [enabled, state, agentStatus, iteration, idleThresholdMs, cooldownMs, maxIterations, autonomous, fire])\n\n  const reset = useCallback(() => {\n    setIteration(0)\n    lastFireRef.current = 0\n    lastInteractionRef.current = Date.now()\n    setState(enabled ? 'idle' : 'off')\n  }, [enabled])\n\n  const trigger = useCallback(() => { fire() }, [fire])\n\n  return {\n    state, mode: autonomous ? 'autonomous' : 'standard',\n    iteration, maxIterations, secondsRemaining,\n    reset, trigger,\n  }\n}\n"]}