@agent-native/core 0.7.21 → 0.7.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. package/dist/agent/engine/ai-sdk-engine.d.ts.map +1 -1
  2. package/dist/agent/engine/ai-sdk-engine.js +43 -1
  3. package/dist/agent/engine/ai-sdk-engine.js.map +1 -1
  4. package/dist/agent/engine/anthropic-engine.d.ts.map +1 -1
  5. package/dist/agent/engine/anthropic-engine.js +8 -0
  6. package/dist/agent/engine/anthropic-engine.js.map +1 -1
  7. package/dist/agent/engine/builder-engine.d.ts +1 -1
  8. package/dist/agent/engine/builder-engine.d.ts.map +1 -1
  9. package/dist/agent/engine/builder-engine.js +9 -4
  10. package/dist/agent/engine/builder-engine.js.map +1 -1
  11. package/dist/agent/engine/translate-ai-sdk.d.ts.map +1 -1
  12. package/dist/agent/engine/translate-ai-sdk.js +31 -1
  13. package/dist/agent/engine/translate-ai-sdk.js.map +1 -1
  14. package/dist/agent/engine/translate-anthropic.d.ts.map +1 -1
  15. package/dist/agent/engine/translate-anthropic.js +16 -0
  16. package/dist/agent/engine/translate-anthropic.js.map +1 -1
  17. package/dist/agent/engine/types.d.ts +16 -1
  18. package/dist/agent/engine/types.d.ts.map +1 -1
  19. package/dist/agent/engine/types.js.map +1 -1
  20. package/dist/agent/production-agent.d.ts +4 -0
  21. package/dist/agent/production-agent.d.ts.map +1 -1
  22. package/dist/agent/production-agent.js +96 -4
  23. package/dist/agent/production-agent.js.map +1 -1
  24. package/dist/agent/types.d.ts +3 -0
  25. package/dist/agent/types.d.ts.map +1 -1
  26. package/dist/agent/types.js.map +1 -1
  27. package/dist/client/AgentPanel.d.ts.map +1 -1
  28. package/dist/client/AgentPanel.js +5 -5
  29. package/dist/client/AgentPanel.js.map +1 -1
  30. package/dist/client/AssistantChat.d.ts +5 -0
  31. package/dist/client/AssistantChat.d.ts.map +1 -1
  32. package/dist/client/AssistantChat.js +54 -2
  33. package/dist/client/AssistantChat.js.map +1 -1
  34. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  35. package/dist/client/MultiTabAssistantChat.js +33 -2
  36. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  37. package/dist/client/NewWorkspaceAppFlow.d.ts.map +1 -1
  38. package/dist/client/NewWorkspaceAppFlow.js +10 -1
  39. package/dist/client/NewWorkspaceAppFlow.js.map +1 -1
  40. package/dist/client/agent-chat-adapter.d.ts +4 -0
  41. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  42. package/dist/client/agent-chat-adapter.js +5 -1
  43. package/dist/client/agent-chat-adapter.js.map +1 -1
  44. package/dist/client/composer/TiptapComposer.d.ts +6 -1
  45. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  46. package/dist/client/composer/TiptapComposer.js +25 -17
  47. package/dist/client/composer/TiptapComposer.js.map +1 -1
  48. package/dist/client/composer/useVoiceDictation.d.ts +6 -5
  49. package/dist/client/composer/useVoiceDictation.d.ts.map +1 -1
  50. package/dist/client/composer/useVoiceDictation.js +54 -21
  51. package/dist/client/composer/useVoiceDictation.js.map +1 -1
  52. package/dist/client/org/OrgSwitcher.d.ts +3 -1
  53. package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
  54. package/dist/client/org/OrgSwitcher.js +12 -7
  55. package/dist/client/org/OrgSwitcher.js.map +1 -1
  56. package/dist/client/settings/AutomationsSection.d.ts.map +1 -1
  57. package/dist/client/settings/AutomationsSection.js +2 -2
  58. package/dist/client/settings/AutomationsSection.js.map +1 -1
  59. package/dist/client/settings/VoiceTranscriptionSection.d.ts.map +1 -1
  60. package/dist/client/settings/VoiceTranscriptionSection.js +46 -15
  61. package/dist/client/settings/VoiceTranscriptionSection.js.map +1 -1
  62. package/dist/client/tools/ToolViewer.d.ts.map +1 -1
  63. package/dist/client/tools/ToolViewer.js +2 -2
  64. package/dist/client/tools/ToolViewer.js.map +1 -1
  65. package/dist/client/tools/ToolsListPage.d.ts.map +1 -1
  66. package/dist/client/tools/ToolsListPage.js +4 -4
  67. package/dist/client/tools/ToolsListPage.js.map +1 -1
  68. package/dist/client/tools/ToolsSidebarSection.d.ts.map +1 -1
  69. package/dist/client/tools/ToolsSidebarSection.js +2 -2
  70. package/dist/client/tools/ToolsSidebarSection.js.map +1 -1
  71. package/dist/client/transcription/use-live-transcription.d.ts +1 -0
  72. package/dist/client/transcription/use-live-transcription.d.ts.map +1 -1
  73. package/dist/client/transcription/use-live-transcription.js +41 -0
  74. package/dist/client/transcription/use-live-transcription.js.map +1 -1
  75. package/dist/integrations/adapters/email.js +81 -5
  76. package/dist/integrations/adapters/email.js.map +1 -1
  77. package/dist/integrations/plugin.d.ts.map +1 -1
  78. package/dist/integrations/plugin.js +2 -1
  79. package/dist/integrations/plugin.js.map +1 -1
  80. package/dist/integrations/types.d.ts +2 -0
  81. package/dist/integrations/types.d.ts.map +1 -1
  82. package/dist/integrations/types.js.map +1 -1
  83. package/dist/integrations/webhook-handler.js +12 -2
  84. package/dist/integrations/webhook-handler.js.map +1 -1
  85. package/dist/oauth-tokens/store.d.ts.map +1 -1
  86. package/dist/oauth-tokens/store.js +34 -16
  87. package/dist/oauth-tokens/store.js.map +1 -1
  88. package/dist/scripts/db/exec.d.ts.map +1 -1
  89. package/dist/scripts/db/exec.js +32 -23
  90. package/dist/scripts/db/exec.js.map +1 -1
  91. package/dist/scripts/db/patch.d.ts.map +1 -1
  92. package/dist/scripts/db/patch.js +48 -35
  93. package/dist/scripts/db/patch.js.map +1 -1
  94. package/dist/scripts/db/query.d.ts.map +1 -1
  95. package/dist/scripts/db/query.js +22 -13
  96. package/dist/scripts/db/query.js.map +1 -1
  97. package/dist/scripts/db/safety.d.ts +2 -0
  98. package/dist/scripts/db/safety.d.ts.map +1 -0
  99. package/dist/scripts/db/safety.js +67 -0
  100. package/dist/scripts/db/safety.js.map +1 -0
  101. package/dist/scripts/db/scoping.js +4 -4
  102. package/dist/scripts/db/scoping.js.map +1 -1
  103. package/dist/server/email-template.d.ts +5 -0
  104. package/dist/server/email-template.d.ts.map +1 -1
  105. package/dist/server/email-template.js +7 -4
  106. package/dist/server/email-template.js.map +1 -1
  107. package/dist/server/google-auth-plugin.d.ts.map +1 -1
  108. package/dist/server/google-auth-plugin.js +1 -8
  109. package/dist/server/google-auth-plugin.js.map +1 -1
  110. package/dist/server/index.d.ts +3 -2
  111. package/dist/server/index.d.ts.map +1 -1
  112. package/dist/server/index.js +3 -2
  113. package/dist/server/index.js.map +1 -1
  114. package/dist/server/onboarding-html.d.ts.map +1 -1
  115. package/dist/server/onboarding-html.js +3 -10
  116. package/dist/server/onboarding-html.js.map +1 -1
  117. package/dist/server/transcribe-voice.d.ts +9 -9
  118. package/dist/server/transcribe-voice.d.ts.map +1 -1
  119. package/dist/server/transcribe-voice.js +405 -51
  120. package/dist/server/transcribe-voice.js.map +1 -1
  121. package/dist/server/voice-providers-status.d.ts.map +1 -1
  122. package/dist/server/voice-providers-status.js +13 -1
  123. package/dist/server/voice-providers-status.js.map +1 -1
  124. package/dist/settings/store.d.ts.map +1 -1
  125. package/dist/settings/store.js +14 -6
  126. package/dist/settings/store.js.map +1 -1
  127. package/dist/shared/reasoning-effort.d.ts +8 -0
  128. package/dist/shared/reasoning-effort.d.ts.map +1 -0
  129. package/dist/shared/reasoning-effort.js +94 -0
  130. package/dist/shared/reasoning-effort.js.map +1 -0
  131. package/dist/templates/default/public/favicon.svg +1 -13
  132. package/dist/templates/default/public/icon-180.svg +1 -13
  133. package/dist/templates/default/public/icon-192.svg +1 -13
  134. package/dist/templates/default/public/icon-512.svg +1 -13
  135. package/dist/templates/workspace-root/scripts/workspace-dev.ts +2 -0
  136. package/dist/transcription/builder-transcription.d.ts +2 -0
  137. package/dist/transcription/builder-transcription.d.ts.map +1 -1
  138. package/dist/transcription/builder-transcription.js +4 -0
  139. package/dist/transcription/builder-transcription.js.map +1 -1
  140. package/docs/content/voice-input.md +14 -13
  141. package/package.json +1 -1
  142. package/src/templates/default/public/favicon.svg +1 -13
  143. package/src/templates/default/public/icon-180.svg +1 -13
  144. package/src/templates/default/public/icon-192.svg +1 -13
  145. package/src/templates/default/public/icon-512.svg +1 -13
  146. package/src/templates/workspace-root/scripts/workspace-dev.ts +2 -0
@@ -1 +1 @@
1
- {"version":3,"file":"useVoiceDictation.js","sourceRoot":"","sources":["../../../src/client/composer/useVoiceDictation.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Voice dictation hook for the agent composer.\n *\n * Wires three providers behind a single state machine:\n * - \"openai\" — MediaRecorder → POST /_agent-native/transcribe-voice (Whisper)\n * - \"browser\" — Web Speech API (low quality, offline capable)\n * - \"builder\" — reserved (coming soon — same as \"browser\" today)\n *\n * Provider preference lives in application_state under\n * `voice-transcription-prefs` (`{ provider: \"openai\" | \"browser\" }`).\n * The composer reads it on every start so settings changes take effect\n * immediately without unmounting the composer.\n *\n * The hook exposes amplitude (0..1) and duration (ms) so the composer can\n * render the Lovable-style live waveform + MM:SS timer.\n */\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { agentNativePath } from \"../api-path.js\";\n\nexport type VoiceProvider =\n | \"openai\"\n | \"browser\"\n | \"builder\"\n | \"gemini\"\n | \"groq\";\n\nexport interface VoicePrefs {\n provider: VoiceProvider;\n}\n\nconst PREFS_KEY = \"voice-transcription-prefs\";\nconst PREFS_URL = agentNativePath(\n `/_agent-native/application-state/${PREFS_KEY}`,\n);\nconst TRANSCRIBE_URL = agentNativePath(\"/_agent-native/transcribe-voice\");\n\nexport type VoiceState =\n | \"idle\"\n | \"starting\"\n | \"recording\"\n | \"transcribing\"\n | \"error\";\n\nexport interface UseVoiceDictationOptions {\n onTranscript: (text: string) => void;\n onError?: (message: string) => void;\n /** Called with (accumulatedFinalText, currentInterimText) as speech is recognized in real time. */\n onLiveUpdate?: (finalText: string, interimText: string) => void;\n}\n\nexport interface VoiceDictationApi {\n state: VoiceState;\n amplitude: number;\n durationMs: number;\n errorMessage: string | null;\n provider: VoiceProvider;\n supported: boolean;\n start: () => Promise<void>;\n stop: () => void;\n cancel: () => void;\n}\n\nasync function readProviderPrefs(): Promise<VoiceProvider> {\n try {\n const res = await fetch(PREFS_URL);\n if (!res.ok) return \"browser\";\n const body = (await res.json()) as\n | VoicePrefs\n | { value?: VoicePrefs }\n | null;\n const p =\n (body as VoicePrefs | null)?.provider ??\n (body as { value?: VoicePrefs } | null)?.value?.provider;\n if (\n p === \"openai\" ||\n p === \"browser\" ||\n p === \"builder\" ||\n p === \"gemini\" ||\n p === \"groq\"\n )\n return p;\n } catch {\n /* fall through */\n }\n return \"browser\";\n}\n\nfunction getSpeechRecognitionCtor(): any {\n if (typeof window === \"undefined\") return null;\n return (\n (window as any).SpeechRecognition ||\n (window as any).webkitSpeechRecognition ||\n null\n );\n}\n\nfunction pickMimeType(): string {\n if (typeof MediaRecorder === \"undefined\") return \"audio/webm\";\n const candidates = [\n \"audio/webm;codecs=opus\",\n \"audio/webm\",\n \"audio/mp4\",\n \"audio/ogg;codecs=opus\",\n ];\n for (const mime of candidates) {\n try {\n if (MediaRecorder.isTypeSupported(mime)) return mime;\n } catch {\n /* ignore */\n }\n }\n return \"audio/webm\";\n}\n\nexport function useVoiceDictation(\n options: UseVoiceDictationOptions,\n): VoiceDictationApi {\n const { onTranscript, onError, onLiveUpdate } = options;\n const onTranscriptRef = useRef(onTranscript);\n const onErrorRef = useRef(onError);\n const onLiveUpdateRef = useRef(onLiveUpdate);\n onTranscriptRef.current = onTranscript;\n onErrorRef.current = onError;\n onLiveUpdateRef.current = onLiveUpdate;\n\n const [state, setState] = useState<VoiceState>(\"idle\");\n const [amplitude, setAmplitude] = useState(0);\n const [durationMs, setDurationMs] = useState(0);\n const [errorMessage, setErrorMessage] = useState<string | null>(null);\n const [provider, setProvider] = useState<VoiceProvider>(\"browser\");\n\n // Keep refs for teardown / cross-branch access.\n const mediaStreamRef = useRef<MediaStream | null>(null);\n const mediaRecorderRef = useRef<MediaRecorder | null>(null);\n const chunksRef = useRef<Blob[]>([]);\n const audioContextRef = useRef<AudioContext | null>(null);\n const analyserRef = useRef<AnalyserNode | null>(null);\n const rafRef = useRef<number | null>(null);\n const timerRef = useRef<ReturnType<typeof setInterval> | null>(null);\n const startedAtRef = useRef<number>(0);\n const cancelledRef = useRef(false);\n const speechRef = useRef<any>(null);\n const speechTranscriptRef = useRef<string>(\"\");\n const activeProviderRef = useRef<VoiceProvider>(\"browser\");\n // Parallel live recognition for OpenAI mode (provides instant preview while MediaRecorder captures)\n const liveSpeechRef = useRef<any>(null);\n const liveTextRef = useRef<string>(\"\");\n\n const mediaRecorderSupported =\n typeof window !== \"undefined\" &&\n typeof navigator !== \"undefined\" &&\n !!navigator.mediaDevices?.getUserMedia &&\n typeof (window as any).MediaRecorder !== \"undefined\";\n const speechSupported = !!getSpeechRecognitionCtor();\n const supported = mediaRecorderSupported || speechSupported;\n\n const teardown = useCallback(() => {\n if (rafRef.current != null) {\n cancelAnimationFrame(rafRef.current);\n rafRef.current = null;\n }\n if (timerRef.current != null) {\n clearInterval(timerRef.current);\n timerRef.current = null;\n }\n if (mediaStreamRef.current) {\n for (const track of mediaStreamRef.current.getTracks()) {\n track.stop();\n }\n mediaStreamRef.current = null;\n }\n if (audioContextRef.current) {\n audioContextRef.current.close().catch(() => {});\n audioContextRef.current = null;\n }\n if (speechRef.current) {\n // Stop the Web Speech session before dropping the ref so the browser\n // releases the mic and stops dispatching onresult events into a stale\n // closure. abort() is fire-and-forget (no final result); stop() would\n // deliver remaining partials but we've already cleared state.\n try {\n speechRef.current.abort?.();\n } catch {\n /* ignore */\n }\n }\n if (liveSpeechRef.current) {\n try {\n liveSpeechRef.current.abort?.();\n } catch {\n /* ignore */\n }\n liveSpeechRef.current = null;\n }\n analyserRef.current = null;\n mediaRecorderRef.current = null;\n chunksRef.current = [];\n speechRef.current = null;\n speechTranscriptRef.current = \"\";\n liveTextRef.current = \"\";\n setAmplitude(0);\n }, []);\n\n useEffect(() => teardown, [teardown]);\n\n const failWith = useCallback(\n (message: string) => {\n setErrorMessage(message);\n setState(\"error\");\n onErrorRef.current?.(message);\n teardown();\n },\n [teardown],\n );\n\n const startMeter = useCallback((stream: MediaStream) => {\n try {\n const AudioCtor =\n typeof window !== \"undefined\"\n ? window.AudioContext || (window as any).webkitAudioContext || null\n : null;\n if (!AudioCtor) return;\n const ctx: AudioContext = new AudioCtor();\n const source = ctx.createMediaStreamSource(stream);\n const analyser = ctx.createAnalyser();\n analyser.fftSize = 512;\n source.connect(analyser);\n audioContextRef.current = ctx;\n analyserRef.current = analyser;\n\n const buffer = new Uint8Array(analyser.frequencyBinCount);\n const tick = () => {\n if (!analyserRef.current) return;\n analyserRef.current.getByteTimeDomainData(buffer);\n let sumSquares = 0;\n for (let i = 0; i < buffer.length; i++) {\n const n = (buffer[i] - 128) / 128;\n sumSquares += n * n;\n }\n const rms = Math.sqrt(sumSquares / buffer.length);\n setAmplitude(Math.min(1, rms * 2.5));\n rafRef.current = requestAnimationFrame(tick);\n };\n rafRef.current = requestAnimationFrame(tick);\n } catch {\n /* analyser is best-effort */\n }\n }, []);\n\n const startTimer = useCallback(() => {\n startedAtRef.current = Date.now();\n setDurationMs(0);\n timerRef.current = setInterval(() => {\n setDurationMs(Date.now() - startedAtRef.current);\n }, 100);\n }, []);\n\n const startOpenAi = useCallback(async () => {\n const stream = await navigator.mediaDevices.getUserMedia({ audio: true });\n // User may have pressed Escape (cancel) while the permission prompt was\n // open. If so, stop the stream and bail before we start recording.\n if (cancelledRef.current) {\n for (const track of stream.getTracks()) track.stop();\n cancelledRef.current = false;\n setState(\"idle\");\n return;\n }\n mediaStreamRef.current = stream;\n const mimeType = pickMimeType();\n const recorder = new MediaRecorder(stream, { mimeType });\n mediaRecorderRef.current = recorder;\n chunksRef.current = [];\n\n recorder.ondataavailable = (e) => {\n if (e.data && e.data.size > 0) chunksRef.current.push(e.data);\n };\n recorder.onstop = async () => {\n const localChunks = chunksRef.current.slice();\n const localMime = recorder.mimeType || mimeType;\n const liveSnapshot = liveTextRef.current;\n teardown();\n if (cancelledRef.current) {\n cancelledRef.current = false;\n setState(\"idle\");\n return;\n }\n if (localChunks.length === 0) {\n if (liveSnapshot) onTranscriptRef.current?.(liveSnapshot.trim());\n setState(\"idle\");\n return;\n }\n setState(\"transcribing\");\n try {\n const audioBlob = new Blob(localChunks, { type: localMime });\n const form = new FormData();\n form.append(\n \"audio\",\n audioBlob,\n `voice.${localMime.split(\"/\")[1] ?? \"webm\"}`,\n );\n const res = await fetch(TRANSCRIBE_URL, {\n method: \"POST\",\n body: form,\n });\n if (!res.ok) {\n const body = await res\n .json()\n .catch(() => ({ error: `HTTP ${res.status}` }));\n throw new Error(body.error || `Transcription failed (${res.status})`);\n }\n const data = (await res.json()) as { text?: string };\n const text = (data.text ?? \"\").trim();\n if (text) {\n onTranscriptRef.current?.(text);\n } else if (liveSnapshot) {\n onTranscriptRef.current?.(liveSnapshot.trim());\n }\n setState(\"idle\");\n } catch (err) {\n if (liveSnapshot) {\n onTranscriptRef.current?.(liveSnapshot.trim());\n setState(\"idle\");\n } else {\n failWith(\n (err as Error)?.message ??\n \"Transcription failed. Check your OpenAI key in settings.\",\n );\n }\n }\n };\n\n startMeter(stream);\n startTimer();\n setState(\"recording\");\n recorder.start();\n\n // Start parallel Web Speech recognition for live preview text.\n // This runs alongside MediaRecorder so the user sees words appear\n // immediately while Whisper processes the full recording later.\n const SpeechCtor = getSpeechRecognitionCtor();\n if (SpeechCtor) {\n const liveSpeech = new SpeechCtor();\n liveSpeech.continuous = true;\n liveSpeech.interimResults = true;\n liveSpeech.lang =\n (typeof navigator !== \"undefined\" && navigator.language) || \"en-US\";\n liveSpeechRef.current = liveSpeech;\n liveTextRef.current = \"\";\n\n liveSpeech.onresult = (event: any) => {\n let interim = \"\";\n for (let i = event.resultIndex; i < event.results.length; i++) {\n const result = event.results[i];\n const text = result[0]?.transcript ?? \"\";\n if (result.isFinal) {\n liveTextRef.current += text;\n } else {\n interim += text;\n }\n }\n onLiveUpdateRef.current?.(liveTextRef.current, interim);\n };\n\n liveSpeech.onend = () => {\n if (liveSpeechRef.current === liveSpeech) {\n try {\n liveSpeech.start();\n } catch {\n /* ignore */\n }\n }\n };\n\n liveSpeech.onerror = () => {};\n\n try {\n liveSpeech.start();\n } catch {\n /* best effort — live preview just won't appear */\n }\n }\n }, [startMeter, startTimer, teardown, failWith]);\n\n const startBrowser = useCallback(async () => {\n const Ctor = getSpeechRecognitionCtor();\n if (!Ctor) {\n throw new Error(\n \"Your browser doesn't support speech recognition. Add an OpenAI API key in settings for Whisper transcription.\",\n );\n }\n // Still request mic to drive the amplitude meter, so the UI doesn't look\n // dead while the user talks. SpeechRecognition manages its own capture\n // under the hood in most browsers.\n let stream: MediaStream | null = null;\n try {\n stream = await navigator.mediaDevices.getUserMedia({ audio: true });\n mediaStreamRef.current = stream;\n startMeter(stream);\n } catch {\n /* non-fatal — recognition can still work without our analyser */\n }\n\n if (cancelledRef.current) {\n if (stream) for (const track of stream.getTracks()) track.stop();\n mediaStreamRef.current = null;\n cancelledRef.current = false;\n setState(\"idle\");\n return;\n }\n\n const recognition = new Ctor();\n recognition.continuous = true;\n recognition.interimResults = true;\n recognition.lang =\n (typeof navigator !== \"undefined\" && navigator.language) || \"en-US\";\n speechRef.current = recognition;\n speechTranscriptRef.current = \"\";\n\n recognition.onresult = (event: any) => {\n let interim = \"\";\n for (let i = event.resultIndex; i < event.results.length; i++) {\n const result = event.results[i];\n const text = result[0]?.transcript ?? \"\";\n if (result.isFinal) {\n speechTranscriptRef.current += text;\n } else {\n interim += text;\n }\n }\n onLiveUpdateRef.current?.(speechTranscriptRef.current, interim);\n };\n recognition.onerror = (event: any) => {\n if (event?.error === \"no-speech\" || event?.error === \"aborted\") return;\n failWith(\n event?.error === \"not-allowed\"\n ? \"Microphone permission denied. Enable it in your browser settings.\"\n : `Speech recognition error: ${event?.error ?? \"unknown\"}`,\n );\n };\n recognition.onend = () => {\n const text = speechTranscriptRef.current.trim();\n const wasCancelled = cancelledRef.current;\n cancelledRef.current = false;\n teardown();\n if (!wasCancelled && text) onTranscriptRef.current?.(text);\n setState(\"idle\");\n };\n\n startTimer();\n setState(\"recording\");\n recognition.start();\n }, [startMeter, startTimer, teardown, failWith]);\n\n const start = useCallback(async () => {\n if (state === \"recording\" || state === \"starting\") return;\n setErrorMessage(null);\n setState(\"starting\");\n cancelledRef.current = false;\n\n const pref = await readProviderPrefs();\n setProvider(pref);\n\n // \"builder\", \"gemini\", and \"groq\" all use the same client-side flow as\n // \"openai\" (MediaRecorder -> POST to /_agent-native/transcribe-voice).\n // The server route handles routing to the right backend.\n const resolvedProvider: VoiceProvider =\n pref === \"builder\" || pref === \"gemini\" || pref === \"groq\"\n ? \"openai\"\n : pref;\n activeProviderRef.current = resolvedProvider;\n\n try {\n if (resolvedProvider === \"openai\") {\n if (!mediaRecorderSupported) {\n throw new Error(\n \"Your browser doesn't support audio recording. Use the browser provider in Settings → Voice Transcription.\",\n );\n }\n await startOpenAi();\n } else {\n await startBrowser();\n }\n } catch (err) {\n const message =\n (err as Error)?.name === \"NotAllowedError\"\n ? \"Microphone permission denied. Enable it in your browser settings.\"\n : ((err as Error)?.message ?? \"Could not start recording\");\n failWith(message);\n }\n }, [state, mediaRecorderSupported, startOpenAi, startBrowser, failWith]);\n\n const stop = useCallback(() => {\n if (state !== \"recording\") return;\n cancelledRef.current = false;\n if (activeProviderRef.current === \"openai\" && mediaRecorderRef.current) {\n try {\n mediaRecorderRef.current.stop();\n } catch {\n teardown();\n setState(\"idle\");\n }\n } else if (speechRef.current) {\n try {\n speechRef.current.stop();\n } catch {\n teardown();\n setState(\"idle\");\n }\n } else {\n teardown();\n setState(\"idle\");\n }\n }, [state, teardown]);\n\n const cancel = useCallback(() => {\n if (state !== \"recording\" && state !== \"starting\") return;\n cancelledRef.current = true;\n if (activeProviderRef.current === \"openai\" && mediaRecorderRef.current) {\n try {\n mediaRecorderRef.current.stop();\n } catch {\n /* ignore */\n }\n } else if (speechRef.current) {\n try {\n speechRef.current.abort?.();\n } catch {\n /* ignore */\n }\n }\n teardown();\n setState(\"idle\");\n }, [state, teardown]);\n\n return {\n state,\n amplitude,\n durationMs,\n errorMessage,\n provider,\n supported,\n start,\n stop,\n cancel,\n };\n}\n"]}
1
+ {"version":3,"file":"useVoiceDictation.js","sourceRoot":"","sources":["../../../src/client/composer/useVoiceDictation.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Voice dictation hook for the agent composer.\n *\n * Wires voice providers behind a single state machine:\n * - \"openai\" / \"builder\" / \"builder-gemini\" / \"gemini\" / \"groq\"\n * — MediaRecorder → POST /_agent-native/transcribe-voice\n * - \"browser\" — Web Speech API (low quality, offline capable)\n *\n * Provider preference lives in application_state under\n * `voice-transcription-prefs` (`{ provider: VoiceProvider, instructions?: string }`).\n * The composer reads it on every start so settings changes take effect\n * immediately without unmounting the composer.\n *\n * The hook exposes amplitude (0..1) and duration (ms) so the composer can\n * render the Lovable-style live waveform + MM:SS timer.\n */\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { agentNativePath } from \"../api-path.js\";\n\nexport type VoiceProvider =\n | \"openai\"\n | \"browser\"\n | \"builder-gemini\"\n | \"builder\"\n | \"gemini\"\n | \"groq\";\n\nexport interface VoicePrefs {\n provider: VoiceProvider;\n instructions?: string;\n}\n\nconst PREFS_KEY = \"voice-transcription-prefs\";\nconst PREFS_URL = agentNativePath(\n `/_agent-native/application-state/${PREFS_KEY}`,\n);\nconst TRANSCRIBE_URL = agentNativePath(\"/_agent-native/transcribe-voice\");\nconst PROVIDER_STATUS_URL = agentNativePath(\n \"/_agent-native/voice-providers/status\",\n);\n\ninterface ProviderStatus {\n builder?: boolean;\n}\n\nfunction isVoiceProvider(value: unknown): value is VoiceProvider {\n return (\n value === \"openai\" ||\n value === \"browser\" ||\n value === \"builder-gemini\" ||\n value === \"builder\" ||\n value === \"gemini\" ||\n value === \"groq\"\n );\n}\n\nasync function defaultProvider(): Promise<VoiceProvider> {\n try {\n const res = await fetch(PROVIDER_STATUS_URL);\n if (!res.ok) return \"browser\";\n const status = (await res.json()) as ProviderStatus | null;\n if (status?.builder) return \"builder-gemini\";\n } catch {\n /* fall through */\n }\n return \"browser\";\n}\n\nexport type VoiceState =\n | \"idle\"\n | \"starting\"\n | \"recording\"\n | \"transcribing\"\n | \"error\";\n\nexport interface UseVoiceDictationOptions {\n onTranscript: (text: string) => void;\n onError?: (message: string) => void;\n /** Called with (accumulatedFinalText, currentInterimText) as speech is recognized in real time. */\n onLiveUpdate?: (finalText: string, interimText: string) => void;\n}\n\nexport interface VoiceDictationApi {\n state: VoiceState;\n amplitude: number;\n durationMs: number;\n errorMessage: string | null;\n provider: VoiceProvider;\n supported: boolean;\n start: () => Promise<void>;\n stop: () => void;\n cancel: () => void;\n}\n\nasync function readVoicePrefs(): Promise<VoicePrefs> {\n try {\n const res = await fetch(PREFS_URL);\n if (!res.ok) return { provider: await defaultProvider() };\n const body = (await res.json()) as\n | VoicePrefs\n | { value?: VoicePrefs }\n | null;\n const p =\n (body as VoicePrefs | null)?.provider ??\n (body as { value?: VoicePrefs } | null)?.value?.provider;\n const instructions =\n (body as VoicePrefs | null)?.instructions ??\n (body as { value?: VoicePrefs } | null)?.value?.instructions;\n if (isVoiceProvider(p)) {\n return {\n provider: p === \"builder\" ? \"builder-gemini\" : p,\n instructions:\n typeof instructions === \"string\" ? instructions.trim() : undefined,\n };\n }\n } catch {\n /* fall through */\n }\n return { provider: await defaultProvider() };\n}\n\nfunction getSpeechRecognitionCtor(): any {\n if (typeof window === \"undefined\") return null;\n return (\n (window as any).SpeechRecognition ||\n (window as any).webkitSpeechRecognition ||\n null\n );\n}\n\nfunction pickMimeType(): string {\n if (typeof MediaRecorder === \"undefined\") return \"audio/webm\";\n const candidates = [\n \"audio/webm;codecs=opus\",\n \"audio/webm\",\n \"audio/mp4\",\n \"audio/ogg;codecs=opus\",\n ];\n for (const mime of candidates) {\n try {\n if (MediaRecorder.isTypeSupported(mime)) return mime;\n } catch {\n /* ignore */\n }\n }\n return \"audio/webm\";\n}\n\nexport function useVoiceDictation(\n options: UseVoiceDictationOptions,\n): VoiceDictationApi {\n const { onTranscript, onError, onLiveUpdate } = options;\n const onTranscriptRef = useRef(onTranscript);\n const onErrorRef = useRef(onError);\n const onLiveUpdateRef = useRef(onLiveUpdate);\n onTranscriptRef.current = onTranscript;\n onErrorRef.current = onError;\n onLiveUpdateRef.current = onLiveUpdate;\n\n const [state, setState] = useState<VoiceState>(\"idle\");\n const [amplitude, setAmplitude] = useState(0);\n const [durationMs, setDurationMs] = useState(0);\n const [errorMessage, setErrorMessage] = useState<string | null>(null);\n const [provider, setProvider] = useState<VoiceProvider>(\"browser\");\n\n // Keep refs for teardown / cross-branch access.\n const mediaStreamRef = useRef<MediaStream | null>(null);\n const mediaRecorderRef = useRef<MediaRecorder | null>(null);\n const chunksRef = useRef<Blob[]>([]);\n const audioContextRef = useRef<AudioContext | null>(null);\n const analyserRef = useRef<AnalyserNode | null>(null);\n const rafRef = useRef<number | null>(null);\n const timerRef = useRef<ReturnType<typeof setInterval> | null>(null);\n const startedAtRef = useRef<number>(0);\n const cancelledRef = useRef(false);\n const speechRef = useRef<any>(null);\n const speechTranscriptRef = useRef<string>(\"\");\n const activeProviderRef = useRef<VoiceProvider>(\"browser\");\n // Parallel live recognition for OpenAI mode (provides instant preview while MediaRecorder captures)\n const liveSpeechRef = useRef<any>(null);\n const liveTextRef = useRef<string>(\"\");\n\n const mediaRecorderSupported =\n typeof window !== \"undefined\" &&\n typeof navigator !== \"undefined\" &&\n !!navigator.mediaDevices?.getUserMedia &&\n typeof (window as any).MediaRecorder !== \"undefined\";\n const speechSupported = !!getSpeechRecognitionCtor();\n const supported = mediaRecorderSupported || speechSupported;\n\n const teardown = useCallback(() => {\n if (rafRef.current != null) {\n cancelAnimationFrame(rafRef.current);\n rafRef.current = null;\n }\n if (timerRef.current != null) {\n clearInterval(timerRef.current);\n timerRef.current = null;\n }\n if (mediaStreamRef.current) {\n for (const track of mediaStreamRef.current.getTracks()) {\n track.stop();\n }\n mediaStreamRef.current = null;\n }\n if (audioContextRef.current) {\n audioContextRef.current.close().catch(() => {});\n audioContextRef.current = null;\n }\n if (speechRef.current) {\n // Stop the Web Speech session before dropping the ref so the browser\n // releases the mic and stops dispatching onresult events into a stale\n // closure. abort() is fire-and-forget (no final result); stop() would\n // deliver remaining partials but we've already cleared state.\n try {\n speechRef.current.abort?.();\n } catch {\n /* ignore */\n }\n }\n if (liveSpeechRef.current) {\n try {\n liveSpeechRef.current.abort?.();\n } catch {\n /* ignore */\n }\n liveSpeechRef.current = null;\n }\n analyserRef.current = null;\n mediaRecorderRef.current = null;\n chunksRef.current = [];\n speechRef.current = null;\n speechTranscriptRef.current = \"\";\n liveTextRef.current = \"\";\n setAmplitude(0);\n }, []);\n\n useEffect(() => teardown, [teardown]);\n\n const failWith = useCallback(\n (message: string) => {\n setErrorMessage(message);\n setState(\"error\");\n onErrorRef.current?.(message);\n teardown();\n },\n [teardown],\n );\n\n const startMeter = useCallback((stream: MediaStream) => {\n try {\n const AudioCtor =\n typeof window !== \"undefined\"\n ? window.AudioContext || (window as any).webkitAudioContext || null\n : null;\n if (!AudioCtor) return;\n const ctx: AudioContext = new AudioCtor();\n const source = ctx.createMediaStreamSource(stream);\n const analyser = ctx.createAnalyser();\n analyser.fftSize = 512;\n source.connect(analyser);\n audioContextRef.current = ctx;\n analyserRef.current = analyser;\n\n const buffer = new Uint8Array(analyser.frequencyBinCount);\n const tick = () => {\n if (!analyserRef.current) return;\n analyserRef.current.getByteTimeDomainData(buffer);\n let sumSquares = 0;\n for (let i = 0; i < buffer.length; i++) {\n const n = (buffer[i] - 128) / 128;\n sumSquares += n * n;\n }\n const rms = Math.sqrt(sumSquares / buffer.length);\n setAmplitude(Math.min(1, rms * 2.5));\n rafRef.current = requestAnimationFrame(tick);\n };\n rafRef.current = requestAnimationFrame(tick);\n } catch {\n /* analyser is best-effort */\n }\n }, []);\n\n const startTimer = useCallback(() => {\n startedAtRef.current = Date.now();\n setDurationMs(0);\n timerRef.current = setInterval(() => {\n setDurationMs(Date.now() - startedAtRef.current);\n }, 100);\n }, []);\n\n const startOpenAi = useCallback(\n async (providerPref: VoiceProvider, instructions?: string) => {\n const stream = await navigator.mediaDevices.getUserMedia({ audio: true });\n // User may have pressed Escape (cancel) while the permission prompt was\n // open. If so, stop the stream and bail before we start recording.\n if (cancelledRef.current) {\n for (const track of stream.getTracks()) track.stop();\n cancelledRef.current = false;\n setState(\"idle\");\n return;\n }\n mediaStreamRef.current = stream;\n const mimeType = pickMimeType();\n const recorder = new MediaRecorder(stream, { mimeType });\n mediaRecorderRef.current = recorder;\n chunksRef.current = [];\n\n recorder.ondataavailable = (e) => {\n if (e.data && e.data.size > 0) chunksRef.current.push(e.data);\n };\n recorder.onstop = async () => {\n const localChunks = chunksRef.current.slice();\n const localMime = recorder.mimeType || mimeType;\n const liveSnapshot = liveTextRef.current;\n teardown();\n if (cancelledRef.current) {\n cancelledRef.current = false;\n setState(\"idle\");\n return;\n }\n if (localChunks.length === 0) {\n if (liveSnapshot) onTranscriptRef.current?.(liveSnapshot.trim());\n setState(\"idle\");\n return;\n }\n setState(\"transcribing\");\n try {\n const audioBlob = new Blob(localChunks, { type: localMime });\n const form = new FormData();\n form.append(\n \"audio\",\n audioBlob,\n `voice.${localMime.split(\"/\")[1] ?? \"webm\"}`,\n );\n form.append(\"provider\", providerPref);\n if (instructions?.trim()) {\n form.append(\"instructions\", instructions.trim());\n }\n const res = await fetch(TRANSCRIBE_URL, {\n method: \"POST\",\n body: form,\n });\n if (!res.ok) {\n const body = await res\n .json()\n .catch(() => ({ error: `HTTP ${res.status}` }));\n throw new Error(\n body.error || `Transcription failed (${res.status})`,\n );\n }\n const data = (await res.json()) as { text?: string };\n const text = (data.text ?? \"\").trim();\n if (text) {\n onTranscriptRef.current?.(text);\n } else if (liveSnapshot) {\n onTranscriptRef.current?.(liveSnapshot.trim());\n }\n setState(\"idle\");\n } catch (err) {\n if (liveSnapshot) {\n onTranscriptRef.current?.(liveSnapshot.trim());\n setState(\"idle\");\n } else {\n failWith(\n (err as Error)?.message ??\n \"Transcription failed. Check your voice transcription provider in settings.\",\n );\n }\n }\n };\n\n startMeter(stream);\n startTimer();\n setState(\"recording\");\n recorder.start();\n\n // Start parallel Web Speech recognition for live preview text.\n // This runs alongside MediaRecorder so the user sees words appear\n // immediately while the server provider processes the full recording later.\n const SpeechCtor = getSpeechRecognitionCtor();\n if (SpeechCtor) {\n const liveSpeech = new SpeechCtor();\n liveSpeech.continuous = true;\n liveSpeech.interimResults = true;\n liveSpeech.lang =\n (typeof navigator !== \"undefined\" && navigator.language) || \"en-US\";\n liveSpeechRef.current = liveSpeech;\n liveTextRef.current = \"\";\n\n liveSpeech.onresult = (event: any) => {\n let interim = \"\";\n for (let i = event.resultIndex; i < event.results.length; i++) {\n const result = event.results[i];\n const text = result[0]?.transcript ?? \"\";\n if (result.isFinal) {\n liveTextRef.current += text;\n } else {\n interim += text;\n }\n }\n onLiveUpdateRef.current?.(liveTextRef.current, interim);\n };\n\n liveSpeech.onend = () => {\n if (liveSpeechRef.current === liveSpeech) {\n try {\n liveSpeech.start();\n } catch {\n /* ignore */\n }\n }\n };\n\n liveSpeech.onerror = () => {};\n\n try {\n liveSpeech.start();\n } catch {\n /* best effort — live preview just won't appear */\n }\n }\n },\n [startMeter, startTimer, teardown, failWith],\n );\n\n const startBrowser = useCallback(async () => {\n const Ctor = getSpeechRecognitionCtor();\n if (!Ctor) {\n throw new Error(\n \"Your browser doesn't support speech recognition. Add an OpenAI API key in settings for Whisper transcription.\",\n );\n }\n // Still request mic to drive the amplitude meter, so the UI doesn't look\n // dead while the user talks. SpeechRecognition manages its own capture\n // under the hood in most browsers.\n let stream: MediaStream | null = null;\n try {\n stream = await navigator.mediaDevices.getUserMedia({ audio: true });\n mediaStreamRef.current = stream;\n startMeter(stream);\n } catch {\n /* non-fatal — recognition can still work without our analyser */\n }\n\n if (cancelledRef.current) {\n if (stream) for (const track of stream.getTracks()) track.stop();\n mediaStreamRef.current = null;\n cancelledRef.current = false;\n setState(\"idle\");\n return;\n }\n\n const recognition = new Ctor();\n recognition.continuous = true;\n recognition.interimResults = true;\n recognition.lang =\n (typeof navigator !== \"undefined\" && navigator.language) || \"en-US\";\n speechRef.current = recognition;\n speechTranscriptRef.current = \"\";\n\n recognition.onresult = (event: any) => {\n let interim = \"\";\n for (let i = event.resultIndex; i < event.results.length; i++) {\n const result = event.results[i];\n const text = result[0]?.transcript ?? \"\";\n if (result.isFinal) {\n speechTranscriptRef.current += text;\n } else {\n interim += text;\n }\n }\n onLiveUpdateRef.current?.(speechTranscriptRef.current, interim);\n };\n recognition.onerror = (event: any) => {\n if (event?.error === \"no-speech\" || event?.error === \"aborted\") return;\n failWith(\n event?.error === \"not-allowed\"\n ? \"Microphone permission denied. Enable it in your browser settings.\"\n : `Speech recognition error: ${event?.error ?? \"unknown\"}`,\n );\n };\n recognition.onend = () => {\n const text = speechTranscriptRef.current.trim();\n const wasCancelled = cancelledRef.current;\n cancelledRef.current = false;\n teardown();\n if (!wasCancelled && text) onTranscriptRef.current?.(text);\n setState(\"idle\");\n };\n\n startTimer();\n setState(\"recording\");\n recognition.start();\n }, [startMeter, startTimer, teardown, failWith]);\n\n const start = useCallback(async () => {\n if (state === \"recording\" || state === \"starting\") return;\n setErrorMessage(null);\n setState(\"starting\");\n cancelledRef.current = false;\n\n const prefs = await readVoicePrefs();\n const pref = prefs.provider;\n setProvider(pref);\n\n // Server providers all use the same client-side flow as \"openai\"\n // (MediaRecorder -> POST to /_agent-native/transcribe-voice).\n // The server route handles routing to the right backend.\n const resolvedProvider: VoiceProvider =\n pref === \"builder\" ||\n pref === \"builder-gemini\" ||\n pref === \"gemini\" ||\n pref === \"groq\"\n ? \"openai\"\n : pref;\n activeProviderRef.current = resolvedProvider;\n\n try {\n if (resolvedProvider === \"openai\") {\n if (!mediaRecorderSupported) {\n throw new Error(\n \"Your browser doesn't support audio recording. Use the browser provider in Settings → Voice Transcription.\",\n );\n }\n await startOpenAi(pref, prefs.instructions);\n } else {\n await startBrowser();\n }\n } catch (err) {\n const message =\n (err as Error)?.name === \"NotAllowedError\"\n ? \"Microphone permission denied. Enable it in your browser settings.\"\n : ((err as Error)?.message ?? \"Could not start recording\");\n failWith(message);\n }\n }, [state, mediaRecorderSupported, startOpenAi, startBrowser, failWith]);\n\n const stop = useCallback(() => {\n if (state !== \"recording\") return;\n cancelledRef.current = false;\n if (activeProviderRef.current === \"openai\" && mediaRecorderRef.current) {\n try {\n mediaRecorderRef.current.stop();\n } catch {\n teardown();\n setState(\"idle\");\n }\n } else if (speechRef.current) {\n try {\n speechRef.current.stop();\n } catch {\n teardown();\n setState(\"idle\");\n }\n } else {\n teardown();\n setState(\"idle\");\n }\n }, [state, teardown]);\n\n const cancel = useCallback(() => {\n if (state !== \"recording\" && state !== \"starting\") return;\n cancelledRef.current = true;\n if (activeProviderRef.current === \"openai\" && mediaRecorderRef.current) {\n try {\n mediaRecorderRef.current.stop();\n } catch {\n /* ignore */\n }\n } else if (speechRef.current) {\n try {\n speechRef.current.abort?.();\n } catch {\n /* ignore */\n }\n }\n teardown();\n setState(\"idle\");\n }, [state, teardown]);\n\n return {\n state,\n amplitude,\n durationMs,\n errorMessage,\n provider,\n supported,\n start,\n stop,\n cancel,\n };\n}\n"]}
@@ -2,6 +2,8 @@ export interface OrgSwitcherProps {
2
2
  className?: string;
3
3
  /** Hide entirely when the user only belongs to one org. Default: false. */
4
4
  hideWhenSingle?: boolean;
5
+ /** Keep the switcher's button height reserved while org state is loading. */
6
+ reserveSpace?: boolean;
5
7
  }
6
8
  /**
7
9
  * Compact org switcher button. Shows the active org name; opens a dropdown
@@ -11,5 +13,5 @@ export interface OrgSwitcherProps {
11
13
  *
12
14
  * Headless DOM (no shadcn deps) so it works in any template.
13
15
  */
14
- export declare function OrgSwitcher({ className, hideWhenSingle }: OrgSwitcherProps): import("react/jsx-runtime").JSX.Element;
16
+ export declare function OrgSwitcher({ className, hideWhenSingle, reserveSpace, }: OrgSwitcherProps): import("react/jsx-runtime").JSX.Element;
15
17
  //# sourceMappingURL=OrgSwitcher.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"OrgSwitcher.d.ts","sourceRoot":"","sources":["../../../src/client/org/OrgSwitcher.tsx"],"names":[],"mappings":"AAkBA,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2EAA2E;IAC3E,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAgBD;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,EAAE,SAAS,EAAE,cAAc,EAAE,EAAE,gBAAgB,2CAoS1E"}
1
+ {"version":3,"file":"OrgSwitcher.d.ts","sourceRoot":"","sources":["../../../src/client/org/OrgSwitcher.tsx"],"names":[],"mappings":"AAkBA,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2EAA2E;IAC3E,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,6EAA6E;IAC7E,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAgBD;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,EAC1B,SAAS,EACT,cAAc,EACd,YAAY,GACb,EAAE,gBAAgB,2CAmTlB"}
@@ -24,8 +24,8 @@ function personalLabelFromEmail(email) {
24
24
  *
25
25
  * Headless DOM (no shadcn deps) so it works in any template.
26
26
  */
27
- export function OrgSwitcher({ className, hideWhenSingle }) {
28
- const { data: org } = useOrg();
27
+ export function OrgSwitcher({ className, hideWhenSingle, reserveSpace, }) {
28
+ const { data: org, isLoading } = useOrg();
29
29
  const switchOrg = useSwitchOrg();
30
30
  const createOrg = useCreateOrg();
31
31
  const inviteMember = useInviteMember();
@@ -53,16 +53,21 @@ export function OrgSwitcher({ className, hideWhenSingle }) {
53
53
  setInviteEmail("");
54
54
  }
55
55
  }, [open]);
56
- if (!org || org.email === DEV_MODE_USER_EMAIL)
57
- return null;
56
+ if (!org) {
57
+ return reserveSpace && isLoading ? (_jsx("div", { "aria-hidden": "true", className: `h-8 ${className ?? ""}` })) : null;
58
+ }
59
+ if (org.email === DEV_MODE_USER_EMAIL) {
60
+ return reserveSpace ? (_jsx("div", { "aria-hidden": "true", className: `h-8 ${className ?? ""}` })) : null;
61
+ }
58
62
  const orgs = org.orgs ?? [];
59
63
  const pendingInvitations = org.pendingInvitations ?? [];
60
64
  const orgCount = orgs.length;
61
65
  const hasAny = orgCount > 0 || pendingInvitations.length > 0;
62
- if (!hasAny && !org.email)
63
- return null;
66
+ if (!hasAny && !org.email) {
67
+ return reserveSpace ? (_jsx("div", { "aria-hidden": "true", className: `h-8 ${className ?? ""}` })) : null;
68
+ }
64
69
  if (hideWhenSingle && orgCount < 2 && pendingInvitations.length === 0) {
65
- return null;
70
+ return reserveSpace ? (_jsx("div", { "aria-hidden": "true", className: `h-8 ${className ?? ""}` })) : null;
66
71
  }
67
72
  const canInvite = !!org.orgId && (org.role === "owner" || org.role === "admin");
68
73
  const personalLabel = personalLabelFromEmail(org.email);
@@ -1 +1 @@
1
- {"version":3,"file":"OrgSwitcher.js","sourceRoot":"","sources":["../../../src/client/org/OrgSwitcher.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport {\n IconBuilding,\n IconCheck,\n IconLoader2,\n IconPlus,\n IconSelector,\n IconUserPlus,\n} from \"@tabler/icons-react\";\nimport {\n useOrg,\n useSwitchOrg,\n useCreateOrg,\n useInviteMember,\n useAcceptInvitation,\n} from \"./hooks.js\";\nimport { DEV_MODE_USER_EMAIL } from \"../dev-mode.js\";\n\nexport interface OrgSwitcherProps {\n className?: string;\n /** Hide entirely when the user only belongs to one org. Default: false. */\n hideWhenSingle?: boolean;\n}\n\nfunction personalLabelFromEmail(email: string | null | undefined): string {\n if (!email) return \"Personal\";\n const local = email.split(\"@\")[0] ?? email;\n const cleaned = local.replace(/[._-]+/g, \" \").trim();\n if (!cleaned) return \"Personal\";\n return cleaned\n .split(\" \")\n .filter(Boolean)\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join(\" \");\n}\n\ntype Mode = \"list\" | \"create\" | \"invite\";\n\n/**\n * Compact org switcher button. Shows the active org name; opens a dropdown\n * with the user's other orgs, pending invitations, and inline forms to\n * create a new org or invite a teammate. Renders nothing in solo / dev\n * mode or when the user has no orgs at all and no invites.\n *\n * Headless DOM (no shadcn deps) so it works in any template.\n */\nexport function OrgSwitcher({ className, hideWhenSingle }: OrgSwitcherProps) {\n const { data: org } = useOrg();\n const switchOrg = useSwitchOrg();\n const createOrg = useCreateOrg();\n const inviteMember = useInviteMember();\n const acceptInvitation = useAcceptInvitation();\n const [open, setOpen] = useState(false);\n const [mode, setMode] = useState<Mode>(\"list\");\n const [newName, setNewName] = useState(\"\");\n const [inviteEmail, setInviteEmail] = useState(\"\");\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!open) return;\n const onClick = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) {\n setOpen(false);\n }\n };\n document.addEventListener(\"mousedown\", onClick);\n return () => document.removeEventListener(\"mousedown\", onClick);\n }, [open]);\n\n useEffect(() => {\n if (!open) {\n setMode(\"list\");\n setNewName(\"\");\n setInviteEmail(\"\");\n }\n }, [open]);\n\n if (!org || org.email === DEV_MODE_USER_EMAIL) return null;\n\n const orgs = org.orgs ?? [];\n const pendingInvitations = org.pendingInvitations ?? [];\n const orgCount = orgs.length;\n const hasAny = orgCount > 0 || pendingInvitations.length > 0;\n if (!hasAny && !org.email) return null;\n if (hideWhenSingle && orgCount < 2 && pendingInvitations.length === 0) {\n return null;\n }\n\n const canInvite =\n !!org.orgId && (org.role === \"owner\" || org.role === \"admin\");\n\n const personalLabel = personalLabelFromEmail(org.email);\n const label = org.orgName ?? personalLabel;\n\n return (\n <div ref={ref} className={`relative ${className ?? \"\"}`}>\n <button\n type=\"button\"\n onClick={() => setOpen((v) => !v)}\n className=\"flex w-full items-center gap-2 rounded-md px-2.5 py-1.5 text-xs font-medium text-muted-foreground hover:bg-accent/50 hover:text-foreground border border-border/50\"\n >\n <IconBuilding className=\"h-3.5 w-3.5 shrink-0\" />\n <span className=\"truncate flex-1 text-left\">{label}</span>\n <IconSelector className=\"h-3 w-3 shrink-0 opacity-50\" />\n </button>\n {open && (\n <div className=\"absolute left-0 right-0 bottom-full mb-1 z-50 rounded-md border border-border bg-popover shadow-md py-1 min-w-[14rem]\">\n {mode === \"list\" && (\n <>\n {(orgs.length > 0 || !org.orgId) && (\n <div className=\"px-2.5 pt-1 pb-0.5 text-[10px] uppercase tracking-wide text-muted-foreground\">\n Organization\n </div>\n )}\n {orgs.length === 0 && !org.orgId && (\n <div\n className=\"flex w-full items-center gap-2 px-2.5 py-1.5 text-xs text-muted-foreground\"\n aria-disabled=\"true\"\n >\n <IconBuilding className=\"h-3.5 w-3.5 shrink-0\" />\n <span className=\"truncate flex-1 text-left\">\n {personalLabel}\n </span>\n <IconCheck className=\"h-3.5 w-3.5 shrink-0 opacity-50\" />\n </div>\n )}\n {orgs.map((o) => (\n <button\n key={o.orgId}\n type=\"button\"\n onClick={async () => {\n if (o.orgId === org.orgId) {\n setOpen(false);\n return;\n }\n try {\n await switchOrg.mutateAsync(o.orgId);\n setOpen(false);\n } catch {\n /* error surfaced via switchOrg.error */\n }\n }}\n disabled={switchOrg.isPending}\n className=\"flex w-full items-center gap-2 px-2.5 py-1.5 text-xs text-foreground hover:bg-accent disabled:opacity-50\"\n >\n <IconBuilding className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n <span className=\"truncate flex-1 text-left\">{o.orgName}</span>\n {o.orgId === org.orgId && (\n <IconCheck className=\"h-3.5 w-3.5 shrink-0 text-green-500\" />\n )}\n </button>\n ))}\n\n {pendingInvitations.length > 0 && (\n <>\n {orgs.length > 0 && <div className=\"my-1 h-px bg-border\" />}\n <div className=\"px-2.5 pt-1 pb-0.5 text-[10px] uppercase tracking-wide text-muted-foreground\">\n Invitations\n </div>\n {pendingInvitations.map((inv) => (\n <div\n key={inv.id}\n className=\"flex items-center gap-2 px-2.5 py-1.5 text-xs\"\n >\n <IconBuilding className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n <span className=\"truncate flex-1 text-foreground\">\n {inv.orgName}\n </span>\n <button\n type=\"button\"\n onClick={async () => {\n try {\n await acceptInvitation.mutateAsync(inv.id);\n setOpen(false);\n } catch {\n /* error surfaced via acceptInvitation.error */\n }\n }}\n disabled={acceptInvitation.isPending}\n className=\"rounded px-1.5 py-0.5 text-[11px] font-medium text-green-600 hover:bg-green-500/10 disabled:opacity-50\"\n >\n {acceptInvitation.isPending ? (\n <IconLoader2 className=\"h-3 w-3 animate-spin\" />\n ) : (\n \"Join\"\n )}\n </button>\n </div>\n ))}\n </>\n )}\n\n <div className=\"my-1 h-px bg-border\" />\n <button\n type=\"button\"\n onClick={() => setMode(\"create\")}\n className=\"flex w-full items-center gap-2 px-2.5 py-1.5 text-xs text-foreground hover:bg-accent\"\n >\n <IconPlus className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n <span className=\"flex-1 text-left\">Create organization</span>\n </button>\n {canInvite && (\n <button\n type=\"button\"\n onClick={() => setMode(\"invite\")}\n className=\"flex w-full items-center gap-2 px-2.5 py-1.5 text-xs text-foreground hover:bg-accent\"\n >\n <IconUserPlus className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n <span className=\"flex-1 text-left\">Invite member</span>\n </button>\n )}\n\n {(switchOrg.error || acceptInvitation.error) && (\n <div className=\"px-2.5 pt-1 text-[11px] text-red-600\">\n {\n ((switchOrg.error || acceptInvitation.error) as Error)\n .message\n }\n </div>\n )}\n </>\n )}\n\n {mode === \"create\" && (\n <form\n onSubmit={async (e) => {\n e.preventDefault();\n const name = newName.trim();\n if (!name) return;\n try {\n await createOrg.mutateAsync(name);\n setOpen(false);\n } catch {\n /* error surfaced via createOrg.error */\n }\n }}\n className=\"px-2 py-1.5\"\n >\n <div className=\"px-0.5 pb-1 text-[10px] uppercase tracking-wide text-muted-foreground\">\n New organization\n </div>\n <input\n autoFocus\n value={newName}\n onChange={(e) => setNewName(e.target.value)}\n placeholder=\"Organization name\"\n disabled={createOrg.isPending}\n className=\"w-full rounded-md border border-input bg-background px-2 py-1.5 text-xs outline-none focus:ring-2 focus:ring-ring disabled:opacity-50\"\n />\n {createOrg.error && (\n <div className=\"pt-1 text-[11px] text-red-600\">\n {(createOrg.error as Error).message}\n </div>\n )}\n <div className=\"flex items-center gap-1.5 pt-1.5\">\n <button\n type=\"button\"\n onClick={() => setMode(\"list\")}\n disabled={createOrg.isPending}\n className=\"flex-1 rounded-md px-2 py-1 text-xs text-muted-foreground hover:bg-accent disabled:opacity-50\"\n >\n Cancel\n </button>\n <button\n type=\"submit\"\n disabled={createOrg.isPending || !newName.trim()}\n className=\"flex-1 rounded-md bg-primary px-2 py-1 text-xs font-medium text-primary-foreground hover:opacity-90 disabled:opacity-50\"\n >\n {createOrg.isPending ? (\n <IconLoader2 className=\"mx-auto h-3 w-3 animate-spin\" />\n ) : (\n \"Create\"\n )}\n </button>\n </div>\n </form>\n )}\n\n {mode === \"invite\" && (\n <form\n onSubmit={async (e) => {\n e.preventDefault();\n const email = inviteEmail.trim();\n if (!email) return;\n try {\n await inviteMember.mutateAsync(email);\n setInviteEmail(\"\");\n setMode(\"list\");\n } catch {\n /* error surfaced via inviteMember.error */\n }\n }}\n className=\"px-2 py-1.5\"\n >\n <div className=\"px-0.5 pb-1 text-[10px] uppercase tracking-wide text-muted-foreground\">\n Invite to {org.orgName}\n </div>\n <input\n autoFocus\n type=\"email\"\n value={inviteEmail}\n onChange={(e) => setInviteEmail(e.target.value)}\n placeholder=\"teammate@company.com\"\n disabled={inviteMember.isPending}\n className=\"w-full rounded-md border border-input bg-background px-2 py-1.5 text-xs outline-none focus:ring-2 focus:ring-ring disabled:opacity-50\"\n />\n {inviteMember.error && (\n <div className=\"pt-1 text-[11px] text-red-600\">\n {(inviteMember.error as Error).message}\n </div>\n )}\n <div className=\"flex items-center gap-1.5 pt-1.5\">\n <button\n type=\"button\"\n onClick={() => setMode(\"list\")}\n disabled={inviteMember.isPending}\n className=\"flex-1 rounded-md px-2 py-1 text-xs text-muted-foreground hover:bg-accent disabled:opacity-50\"\n >\n Cancel\n </button>\n <button\n type=\"submit\"\n disabled={inviteMember.isPending || !inviteEmail.trim()}\n className=\"flex-1 rounded-md bg-primary px-2 py-1 text-xs font-medium text-primary-foreground hover:opacity-90 disabled:opacity-50\"\n >\n {inviteMember.isPending ? (\n <IconLoader2 className=\"mx-auto h-3 w-3 animate-spin\" />\n ) : (\n \"Send invite\"\n )}\n </button>\n </div>\n </form>\n )}\n </div>\n )}\n </div>\n );\n}\n"]}
1
+ {"version":3,"file":"OrgSwitcher.js","sourceRoot":"","sources":["../../../src/client/org/OrgSwitcher.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport {\n IconBuilding,\n IconCheck,\n IconLoader2,\n IconPlus,\n IconSelector,\n IconUserPlus,\n} from \"@tabler/icons-react\";\nimport {\n useOrg,\n useSwitchOrg,\n useCreateOrg,\n useInviteMember,\n useAcceptInvitation,\n} from \"./hooks.js\";\nimport { DEV_MODE_USER_EMAIL } from \"../dev-mode.js\";\n\nexport interface OrgSwitcherProps {\n className?: string;\n /** Hide entirely when the user only belongs to one org. Default: false. */\n hideWhenSingle?: boolean;\n /** Keep the switcher's button height reserved while org state is loading. */\n reserveSpace?: boolean;\n}\n\nfunction personalLabelFromEmail(email: string | null | undefined): string {\n if (!email) return \"Personal\";\n const local = email.split(\"@\")[0] ?? email;\n const cleaned = local.replace(/[._-]+/g, \" \").trim();\n if (!cleaned) return \"Personal\";\n return cleaned\n .split(\" \")\n .filter(Boolean)\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join(\" \");\n}\n\ntype Mode = \"list\" | \"create\" | \"invite\";\n\n/**\n * Compact org switcher button. Shows the active org name; opens a dropdown\n * with the user's other orgs, pending invitations, and inline forms to\n * create a new org or invite a teammate. Renders nothing in solo / dev\n * mode or when the user has no orgs at all and no invites.\n *\n * Headless DOM (no shadcn deps) so it works in any template.\n */\nexport function OrgSwitcher({\n className,\n hideWhenSingle,\n reserveSpace,\n}: OrgSwitcherProps) {\n const { data: org, isLoading } = useOrg();\n const switchOrg = useSwitchOrg();\n const createOrg = useCreateOrg();\n const inviteMember = useInviteMember();\n const acceptInvitation = useAcceptInvitation();\n const [open, setOpen] = useState(false);\n const [mode, setMode] = useState<Mode>(\"list\");\n const [newName, setNewName] = useState(\"\");\n const [inviteEmail, setInviteEmail] = useState(\"\");\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!open) return;\n const onClick = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) {\n setOpen(false);\n }\n };\n document.addEventListener(\"mousedown\", onClick);\n return () => document.removeEventListener(\"mousedown\", onClick);\n }, [open]);\n\n useEffect(() => {\n if (!open) {\n setMode(\"list\");\n setNewName(\"\");\n setInviteEmail(\"\");\n }\n }, [open]);\n\n if (!org) {\n return reserveSpace && isLoading ? (\n <div aria-hidden=\"true\" className={`h-8 ${className ?? \"\"}`} />\n ) : null;\n }\n if (org.email === DEV_MODE_USER_EMAIL) {\n return reserveSpace ? (\n <div aria-hidden=\"true\" className={`h-8 ${className ?? \"\"}`} />\n ) : null;\n }\n\n const orgs = org.orgs ?? [];\n const pendingInvitations = org.pendingInvitations ?? [];\n const orgCount = orgs.length;\n const hasAny = orgCount > 0 || pendingInvitations.length > 0;\n if (!hasAny && !org.email) {\n return reserveSpace ? (\n <div aria-hidden=\"true\" className={`h-8 ${className ?? \"\"}`} />\n ) : null;\n }\n if (hideWhenSingle && orgCount < 2 && pendingInvitations.length === 0) {\n return reserveSpace ? (\n <div aria-hidden=\"true\" className={`h-8 ${className ?? \"\"}`} />\n ) : null;\n }\n\n const canInvite =\n !!org.orgId && (org.role === \"owner\" || org.role === \"admin\");\n\n const personalLabel = personalLabelFromEmail(org.email);\n const label = org.orgName ?? personalLabel;\n\n return (\n <div ref={ref} className={`relative ${className ?? \"\"}`}>\n <button\n type=\"button\"\n onClick={() => setOpen((v) => !v)}\n className=\"flex w-full items-center gap-2 rounded-md px-2.5 py-1.5 text-xs font-medium text-muted-foreground hover:bg-accent/50 hover:text-foreground border border-border/50\"\n >\n <IconBuilding className=\"h-3.5 w-3.5 shrink-0\" />\n <span className=\"truncate flex-1 text-left\">{label}</span>\n <IconSelector className=\"h-3 w-3 shrink-0 opacity-50\" />\n </button>\n {open && (\n <div className=\"absolute left-0 right-0 bottom-full mb-1 z-50 rounded-md border border-border bg-popover shadow-md py-1 min-w-[14rem]\">\n {mode === \"list\" && (\n <>\n {(orgs.length > 0 || !org.orgId) && (\n <div className=\"px-2.5 pt-1 pb-0.5 text-[10px] uppercase tracking-wide text-muted-foreground\">\n Organization\n </div>\n )}\n {orgs.length === 0 && !org.orgId && (\n <div\n className=\"flex w-full items-center gap-2 px-2.5 py-1.5 text-xs text-muted-foreground\"\n aria-disabled=\"true\"\n >\n <IconBuilding className=\"h-3.5 w-3.5 shrink-0\" />\n <span className=\"truncate flex-1 text-left\">\n {personalLabel}\n </span>\n <IconCheck className=\"h-3.5 w-3.5 shrink-0 opacity-50\" />\n </div>\n )}\n {orgs.map((o) => (\n <button\n key={o.orgId}\n type=\"button\"\n onClick={async () => {\n if (o.orgId === org.orgId) {\n setOpen(false);\n return;\n }\n try {\n await switchOrg.mutateAsync(o.orgId);\n setOpen(false);\n } catch {\n /* error surfaced via switchOrg.error */\n }\n }}\n disabled={switchOrg.isPending}\n className=\"flex w-full items-center gap-2 px-2.5 py-1.5 text-xs text-foreground hover:bg-accent disabled:opacity-50\"\n >\n <IconBuilding className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n <span className=\"truncate flex-1 text-left\">{o.orgName}</span>\n {o.orgId === org.orgId && (\n <IconCheck className=\"h-3.5 w-3.5 shrink-0 text-green-500\" />\n )}\n </button>\n ))}\n\n {pendingInvitations.length > 0 && (\n <>\n {orgs.length > 0 && <div className=\"my-1 h-px bg-border\" />}\n <div className=\"px-2.5 pt-1 pb-0.5 text-[10px] uppercase tracking-wide text-muted-foreground\">\n Invitations\n </div>\n {pendingInvitations.map((inv) => (\n <div\n key={inv.id}\n className=\"flex items-center gap-2 px-2.5 py-1.5 text-xs\"\n >\n <IconBuilding className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n <span className=\"truncate flex-1 text-foreground\">\n {inv.orgName}\n </span>\n <button\n type=\"button\"\n onClick={async () => {\n try {\n await acceptInvitation.mutateAsync(inv.id);\n setOpen(false);\n } catch {\n /* error surfaced via acceptInvitation.error */\n }\n }}\n disabled={acceptInvitation.isPending}\n className=\"rounded px-1.5 py-0.5 text-[11px] font-medium text-green-600 hover:bg-green-500/10 disabled:opacity-50\"\n >\n {acceptInvitation.isPending ? (\n <IconLoader2 className=\"h-3 w-3 animate-spin\" />\n ) : (\n \"Join\"\n )}\n </button>\n </div>\n ))}\n </>\n )}\n\n <div className=\"my-1 h-px bg-border\" />\n <button\n type=\"button\"\n onClick={() => setMode(\"create\")}\n className=\"flex w-full items-center gap-2 px-2.5 py-1.5 text-xs text-foreground hover:bg-accent\"\n >\n <IconPlus className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n <span className=\"flex-1 text-left\">Create organization</span>\n </button>\n {canInvite && (\n <button\n type=\"button\"\n onClick={() => setMode(\"invite\")}\n className=\"flex w-full items-center gap-2 px-2.5 py-1.5 text-xs text-foreground hover:bg-accent\"\n >\n <IconUserPlus className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n <span className=\"flex-1 text-left\">Invite member</span>\n </button>\n )}\n\n {(switchOrg.error || acceptInvitation.error) && (\n <div className=\"px-2.5 pt-1 text-[11px] text-red-600\">\n {\n ((switchOrg.error || acceptInvitation.error) as Error)\n .message\n }\n </div>\n )}\n </>\n )}\n\n {mode === \"create\" && (\n <form\n onSubmit={async (e) => {\n e.preventDefault();\n const name = newName.trim();\n if (!name) return;\n try {\n await createOrg.mutateAsync(name);\n setOpen(false);\n } catch {\n /* error surfaced via createOrg.error */\n }\n }}\n className=\"px-2 py-1.5\"\n >\n <div className=\"px-0.5 pb-1 text-[10px] uppercase tracking-wide text-muted-foreground\">\n New organization\n </div>\n <input\n autoFocus\n value={newName}\n onChange={(e) => setNewName(e.target.value)}\n placeholder=\"Organization name\"\n disabled={createOrg.isPending}\n className=\"w-full rounded-md border border-input bg-background px-2 py-1.5 text-xs outline-none focus:ring-2 focus:ring-ring disabled:opacity-50\"\n />\n {createOrg.error && (\n <div className=\"pt-1 text-[11px] text-red-600\">\n {(createOrg.error as Error).message}\n </div>\n )}\n <div className=\"flex items-center gap-1.5 pt-1.5\">\n <button\n type=\"button\"\n onClick={() => setMode(\"list\")}\n disabled={createOrg.isPending}\n className=\"flex-1 rounded-md px-2 py-1 text-xs text-muted-foreground hover:bg-accent disabled:opacity-50\"\n >\n Cancel\n </button>\n <button\n type=\"submit\"\n disabled={createOrg.isPending || !newName.trim()}\n className=\"flex-1 rounded-md bg-primary px-2 py-1 text-xs font-medium text-primary-foreground hover:opacity-90 disabled:opacity-50\"\n >\n {createOrg.isPending ? (\n <IconLoader2 className=\"mx-auto h-3 w-3 animate-spin\" />\n ) : (\n \"Create\"\n )}\n </button>\n </div>\n </form>\n )}\n\n {mode === \"invite\" && (\n <form\n onSubmit={async (e) => {\n e.preventDefault();\n const email = inviteEmail.trim();\n if (!email) return;\n try {\n await inviteMember.mutateAsync(email);\n setInviteEmail(\"\");\n setMode(\"list\");\n } catch {\n /* error surfaced via inviteMember.error */\n }\n }}\n className=\"px-2 py-1.5\"\n >\n <div className=\"px-0.5 pb-1 text-[10px] uppercase tracking-wide text-muted-foreground\">\n Invite to {org.orgName}\n </div>\n <input\n autoFocus\n type=\"email\"\n value={inviteEmail}\n onChange={(e) => setInviteEmail(e.target.value)}\n placeholder=\"teammate@company.com\"\n disabled={inviteMember.isPending}\n className=\"w-full rounded-md border border-input bg-background px-2 py-1.5 text-xs outline-none focus:ring-2 focus:ring-ring disabled:opacity-50\"\n />\n {inviteMember.error && (\n <div className=\"pt-1 text-[11px] text-red-600\">\n {(inviteMember.error as Error).message}\n </div>\n )}\n <div className=\"flex items-center gap-1.5 pt-1.5\">\n <button\n type=\"button\"\n onClick={() => setMode(\"list\")}\n disabled={inviteMember.isPending}\n className=\"flex-1 rounded-md px-2 py-1 text-xs text-muted-foreground hover:bg-accent disabled:opacity-50\"\n >\n Cancel\n </button>\n <button\n type=\"submit\"\n disabled={inviteMember.isPending || !inviteEmail.trim()}\n className=\"flex-1 rounded-md bg-primary px-2 py-1 text-xs font-medium text-primary-foreground hover:opacity-90 disabled:opacity-50\"\n >\n {inviteMember.isPending ? (\n <IconLoader2 className=\"mx-auto h-3 w-3 animate-spin\" />\n ) : (\n \"Send invite\"\n )}\n </button>\n </div>\n </form>\n )}\n </div>\n )}\n </div>\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"AutomationsSection.d.ts","sourceRoot":"","sources":["../../../src/client/settings/AutomationsSection.tsx"],"names":[],"mappings":"AA8EA,wBAAgB,kBAAkB,4CAiZjC"}
1
+ {"version":3,"file":"AutomationsSection.d.ts","sourceRoot":"","sources":["../../../src/client/settings/AutomationsSection.tsx"],"names":[],"mappings":"AA8EA,wBAAgB,kBAAkB,4CAwZjC"}
@@ -190,13 +190,13 @@ export function AutomationsSection() {
190
190
  if (loading) {
191
191
  return (_jsxs("div", { className: "flex items-center gap-1.5 text-[10px] text-muted-foreground", children: [_jsx(IconLoader2, { size: 10, className: "animate-spin" }), "Loading..."] }));
192
192
  }
193
- return (_jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-center gap-1.5", children: [_jsxs("div", { className: "relative", children: [_jsxs("button", { ref: newButtonRef, type: "button", onClick: () => setNewOpen(!newOpen), className: "inline-flex items-center gap-1 rounded border border-border px-2 py-1 text-[10px] font-medium text-muted-foreground hover:text-foreground hover:bg-accent/40", children: [_jsx(IconPlus, { size: 10 }), "New Automation"] }), newOpen && (_jsx("div", { ref: newPopoverRef, className: "absolute left-0 top-full mt-1.5 z-[220] w-72 rounded-lg border border-border bg-popover p-3 shadow-lg", children: _jsxs("form", { onSubmit: handleNewSubmit, children: [_jsx("textarea", { value: newPrompt, onChange: (e) => setNewPrompt(e.target.value), placeholder: "Describe what you want to automate...", className: "w-full resize-y rounded-md border border-border bg-background px-2.5 py-2 text-[12px] text-foreground outline-none placeholder:text-muted-foreground/50 focus:ring-1 focus:ring-ring/50 min-h-[100px]", autoFocus: true, required: true, onKeyDown: (e) => {
193
+ return (_jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-center gap-1.5", children: [_jsxs("div", { className: "relative", children: [_jsxs("button", { ref: newButtonRef, type: "button", onClick: () => setNewOpen(!newOpen), className: "inline-flex items-center gap-1 rounded border border-border px-2 py-1 text-[10px] font-medium text-muted-foreground hover:text-foreground hover:bg-accent/40", children: [_jsx(IconPlus, { size: 10 }), "New Automation"] }), newOpen && (_jsx("div", { ref: newPopoverRef, className: "absolute left-0 top-full mt-1.5 z-[220] w-72 rounded-lg border border-border bg-popover p-3 shadow-lg", children: _jsxs("form", { onSubmit: handleNewSubmit, className: "space-y-2.5", children: [_jsx("p", { className: "text-sm font-semibold text-foreground", children: "New automation" }), _jsx("textarea", { value: newPrompt, onChange: (e) => setNewPrompt(e.target.value), placeholder: "Describe what you want to automate...", className: "w-full resize-y rounded-md border border-border bg-background px-2.5 py-2 text-[12px] text-foreground outline-none placeholder:text-muted-foreground/50 focus:ring-1 focus:ring-ring/50 min-h-[100px]", autoFocus: true, required: true, onKeyDown: (e) => {
194
194
  if ((e.metaKey || e.ctrlKey) && e.key === "Enter") {
195
195
  e.preventDefault();
196
196
  if (newPrompt.trim())
197
197
  handleNewSubmit(e);
198
198
  }
199
- } }), _jsx("div", { className: "mt-2", children: _jsxs("select", { value: newScope, onChange: (e) => setNewScope(e.target.value), className: "w-full rounded-md border border-input bg-background px-3 py-1.5 text-[12px] text-foreground", children: [_jsx("option", { value: "personal", children: "Personal" }), _jsx("option", { value: "organization", children: "Organization" })] }) }), _jsx("div", { className: "mt-2.5 flex justify-end", children: _jsx("button", { type: "submit", disabled: !newPrompt.trim(), className: "rounded-md bg-primary px-3 py-1.5 text-[11px] font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50 disabled:cursor-not-allowed", children: "Create" }) })] }) }))] }), _jsxs("button", { type: "button", onClick: handleFireTestEvent, className: "inline-flex items-center gap-1 rounded border border-border px-2 py-1 text-[10px] font-medium text-muted-foreground hover:text-foreground hover:bg-accent/40", children: [_jsx(IconPlayerPlay, { size: 10 }), "Fire Test Event"] })] }), automations.length === 0 ? (_jsx("p", { className: "text-[10px] text-muted-foreground", children: "No automations yet. Click \"New Automation\" to create one, or ask the agent to set up a scheduled or event-triggered task." })) : (automations.map((item) => (_jsxs("div", { className: "rounded-md border border-border px-2.5 py-2 bg-accent/30", children: [_jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx("span", { className: "text-muted-foreground shrink-0", children: item.schedule ? (_jsx(IconClock, { size: 11 })) : (_jsx(IconBolt, { size: 11 })) }), _jsx("span", { className: "text-[11px] font-medium text-foreground truncate capitalize", children: item.name })] }), item.scheduleDescription && (_jsx("p", { className: "text-[10px] text-muted-foreground mt-0.5 ml-[17px]", children: item.scheduleDescription })), item.schedule && !item.scheduleDescription && (_jsx("p", { className: "text-[10px] text-muted-foreground mt-0.5 ml-[17px] font-mono", children: item.schedule }))] }), _jsxs("div", { className: "flex items-center gap-1.5 shrink-0", children: [_jsx(StatusBadge, { status: item.lastStatus }), _jsx("button", { type: "button", onClick: () => handleToggle(item), disabled: togglingId === item.id, className: `rounded px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide ${item.enabled
199
+ } }), _jsx("div", { children: _jsxs("select", { value: newScope, onChange: (e) => setNewScope(e.target.value), className: "w-full rounded-md border border-input bg-background px-3 py-1.5 text-[12px] text-foreground", children: [_jsx("option", { value: "personal", children: "Personal" }), _jsx("option", { value: "organization", children: "Organization" })] }) }), _jsxs("div", { className: "flex items-center justify-end gap-2", children: [_jsxs("span", { className: "text-[11px] text-muted-foreground/70", children: [/Mac|iPhone|iPad/.test(navigator.userAgent) ? "⌘" : "Ctrl", "+Enter to submit"] }), _jsx("button", { type: "submit", disabled: !newPrompt.trim(), className: "rounded-md bg-primary px-3 py-1.5 text-[11px] font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50 disabled:cursor-not-allowed", children: "Create" })] })] }) }))] }), _jsxs("button", { type: "button", onClick: handleFireTestEvent, className: "inline-flex items-center gap-1 rounded border border-border px-2 py-1 text-[10px] font-medium text-muted-foreground hover:text-foreground hover:bg-accent/40", children: [_jsx(IconPlayerPlay, { size: 10 }), "Fire Test Event"] })] }), automations.length === 0 ? (_jsx("p", { className: "text-[10px] text-muted-foreground", children: "No automations yet. Click \"New Automation\" to create one, or ask the agent to set up a scheduled or event-triggered task." })) : (automations.map((item) => (_jsxs("div", { className: "rounded-md border border-border px-2.5 py-2 bg-accent/30", children: [_jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx("span", { className: "text-muted-foreground shrink-0", children: item.schedule ? (_jsx(IconClock, { size: 11 })) : (_jsx(IconBolt, { size: 11 })) }), _jsx("span", { className: "text-[11px] font-medium text-foreground truncate capitalize", children: item.name })] }), item.scheduleDescription && (_jsx("p", { className: "text-[10px] text-muted-foreground mt-0.5 ml-[17px]", children: item.scheduleDescription })), item.schedule && !item.scheduleDescription && (_jsx("p", { className: "text-[10px] text-muted-foreground mt-0.5 ml-[17px] font-mono", children: item.schedule }))] }), _jsxs("div", { className: "flex items-center gap-1.5 shrink-0", children: [_jsx(StatusBadge, { status: item.lastStatus }), _jsx("button", { type: "button", onClick: () => handleToggle(item), disabled: togglingId === item.id, className: `rounded px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide ${item.enabled
200
200
  ? "bg-green-500/15 text-green-500"
201
201
  : "bg-accent/60 text-muted-foreground"} hover:opacity-80 disabled:opacity-40`, title: item.enabled ? "Disable" : "Enable", children: togglingId === item.id ? (_jsx(IconLoader2, { size: 10, className: "animate-spin" })) : item.enabled ? ("On") : ("Off") }), confirmDeleteId === item.id ? (_jsxs("div", { className: "flex items-center gap-1", children: [_jsx("button", { type: "button", onClick: () => handleDelete(item), disabled: deletingId === item.id, className: "rounded px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide bg-red-500/15 text-red-500 hover:bg-red-500/25 disabled:opacity-40", children: deletingId === item.id ? (_jsx(IconLoader2, { size: 10, className: "animate-spin" })) : ("Confirm") }), _jsx("button", { type: "button", onClick: () => setConfirmDeleteId(null), className: "rounded px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide bg-accent/60 text-muted-foreground hover:text-foreground", children: "Cancel" })] })) : (_jsx("button", { type: "button", onClick: () => setConfirmDeleteId(item.id), className: "text-muted-foreground hover:text-red-500 disabled:opacity-40", title: "Delete", children: _jsx(IconTrash, { size: 12 }) }))] })] }), item.lastRun && (_jsxs("p", { className: "text-[10px] text-muted-foreground mt-1 ml-[17px]", children: ["Last run:", " ", new Date(item.lastRun).toLocaleString(undefined, {
202
202
  month: "short",
@@ -1 +1 @@
1
- {"version":3,"file":"AutomationsSection.js","sourceRoot":"","sources":["../../../src/client/settings/AutomationsSection.tsx"],"names":[],"mappings":"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","sourcesContent":["import { agentNativePath } from \"../api-path.js\";\nimport React, { useEffect, useState, useCallback, useRef } from \"react\";\nimport {\n IconBolt,\n IconClock,\n IconLoader2,\n IconPlayerPlay,\n IconPlus,\n IconTrash,\n} from \"@tabler/icons-react\";\nimport { sendToAgentChat } from \"../agent-chat.js\";\n\ninterface TreeNode {\n name: string;\n path: string;\n type: \"file\" | \"folder\";\n kind?: string;\n children?: TreeNode[];\n resource?: {\n id: string;\n path: string;\n owner: string;\n mimeType: string;\n size: number;\n createdAt: number;\n updatedAt: number;\n };\n jobMeta?: {\n schedule?: string;\n scheduleDescription?: string;\n enabled?: boolean;\n lastStatus?: string;\n lastRun?: string;\n nextRun?: string;\n };\n}\n\ninterface AutomationItem {\n id: string;\n name: string;\n path: string;\n schedule?: string;\n scheduleDescription?: string;\n enabled: boolean;\n lastStatus?: string;\n lastRun?: string;\n nextRun?: string;\n}\n\nfunction flattenJobs(nodes: TreeNode[]): AutomationItem[] {\n const items: AutomationItem[] = [];\n for (const node of nodes) {\n if (node.type === \"folder\" && node.children) {\n items.push(...flattenJobs(node.children));\n }\n if (\n node.type === \"file\" &&\n node.kind === \"job\" &&\n node.resource &&\n node.jobMeta\n ) {\n const name = node.name.replace(/\\.md$/, \"\").replace(/-/g, \" \");\n items.push({\n id: node.resource.id,\n name,\n path: node.resource.path,\n schedule: node.jobMeta.schedule,\n scheduleDescription: node.jobMeta.scheduleDescription,\n enabled: node.jobMeta.enabled ?? false,\n lastStatus: node.jobMeta.lastStatus,\n lastRun: node.jobMeta.lastRun,\n nextRun: node.jobMeta.nextRun,\n });\n }\n }\n return items;\n}\n\nexport function AutomationsSection() {\n const [automations, setAutomations] = useState<AutomationItem[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [togglingId, setTogglingId] = useState<string | null>(null);\n const [deletingId, setDeletingId] = useState<string | null>(null);\n const [confirmDeleteId, setConfirmDeleteId] = useState<string | null>(null);\n const [toast, setToast] = useState<{\n kind: \"ok\" | \"err\";\n text: string;\n } | null>(null);\n const [reloadToken, setReloadToken] = useState(0);\n\n const showToast = useCallback(\n (kind: \"ok\" | \"err\", text: string, ms = 2500) => {\n setToast({ kind, text });\n setTimeout(() => setToast(null), ms);\n },\n [],\n );\n\n useEffect(() => {\n let cancelled = false;\n setLoading(true);\n fetch(agentNativePath(\"/_agent-native/resources/tree\"))\n .then(async (r) => {\n if (!r.ok) throw new Error(`Failed to load (${r.status})`);\n return (await r.json()) as { tree: TreeNode[] };\n })\n .then(({ tree }) => {\n if (cancelled) return;\n const jobsFolder = tree.find(\n (n) => n.name === \"jobs\" && n.type === \"folder\",\n );\n const items = jobsFolder?.children\n ? flattenJobs(jobsFolder.children)\n : [];\n setAutomations(items);\n setLoading(false);\n })\n .catch((err) => {\n if (cancelled) return;\n setError(err?.message ?? \"Failed to load\");\n setLoading(false);\n });\n return () => {\n cancelled = true;\n };\n }, [reloadToken]);\n\n const reload = useCallback(() => setReloadToken((t) => t + 1), []);\n\n const handleToggle = useCallback(\n async (item: AutomationItem) => {\n setTogglingId(item.id);\n try {\n const res = await fetch(\n agentNativePath(\n `/_agent-native/resources/${encodeURIComponent(item.id)}`,\n ),\n );\n if (!res.ok) {\n showToast(\"err\", \"Failed to read automation\");\n return;\n }\n const resource = await res.json();\n const content: string = resource.content ?? \"\";\n\n const newEnabled = !item.enabled;\n const updated = content.replace(\n /^(enabled:\\s*)(true|false)/m,\n `$1${newEnabled}`,\n );\n\n const putRes = await fetch(\n agentNativePath(\n `/_agent-native/resources/${encodeURIComponent(item.id)}`,\n ),\n {\n method: \"PUT\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ content: updated }),\n },\n );\n if (!putRes.ok) {\n showToast(\"err\", \"Failed to update automation\");\n return;\n }\n showToast(\"ok\", newEnabled ? \"Enabled\" : \"Disabled\");\n reload();\n } finally {\n setTogglingId(null);\n }\n },\n [reload, showToast],\n );\n\n const handleDelete = useCallback(\n async (item: AutomationItem) => {\n setDeletingId(item.id);\n try {\n const res = await fetch(\n agentNativePath(\n `/_agent-native/resources/${encodeURIComponent(item.id)}`,\n ),\n {\n method: \"DELETE\",\n headers: { \"Content-Type\": \"application/json\" },\n },\n );\n if (!res.ok) {\n showToast(\"err\", \"Failed to delete automation\");\n return;\n }\n showToast(\"ok\", \"Deleted\");\n setConfirmDeleteId(null);\n reload();\n } finally {\n setDeletingId(null);\n }\n },\n [reload, showToast],\n );\n\n const handleFireTestEvent = useCallback(async () => {\n showToast(\"ok\", \"Firing test event...\");\n try {\n const res = await fetch(\n agentNativePath(\"/_agent-native/automations/fire-test\"),\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ data: {} }),\n },\n );\n if (!res.ok) {\n showToast(\"err\", `Failed to fire event (${res.status})`);\n return;\n }\n showToast(\"ok\", \"Event fired\");\n } catch (err: any) {\n showToast(\"err\", err?.message ?? \"Failed to fire event\");\n }\n }, [showToast]);\n\n const [newOpen, setNewOpen] = useState(false);\n const [newPrompt, setNewPrompt] = useState(\"\");\n const [newScope, setNewScope] = useState<\"personal\" | \"organization\">(\n \"personal\",\n );\n const newPopoverRef = useRef<HTMLDivElement>(null);\n const newButtonRef = useRef<HTMLButtonElement>(null);\n\n // Close popover on outside click\n useEffect(() => {\n if (!newOpen) return;\n function handleClick(e: MouseEvent) {\n if (\n newPopoverRef.current &&\n !newPopoverRef.current.contains(e.target as Node) &&\n newButtonRef.current &&\n !newButtonRef.current.contains(e.target as Node)\n ) {\n setNewOpen(false);\n }\n }\n document.addEventListener(\"mousedown\", handleClick);\n return () => document.removeEventListener(\"mousedown\", handleClick);\n }, [newOpen]);\n\n // Close popover on Escape\n useEffect(() => {\n if (!newOpen) return;\n function handleKey(e: KeyboardEvent) {\n if (e.key === \"Escape\") setNewOpen(false);\n }\n document.addEventListener(\"keydown\", handleKey);\n return () => document.removeEventListener(\"keydown\", handleKey);\n }, [newOpen]);\n\n const handleNewSubmit = useCallback(\n (e: React.FormEvent) => {\n e.preventDefault();\n if (!newPrompt.trim()) return;\n window.dispatchEvent(\n new CustomEvent(\"agent-panel:set-mode\", {\n detail: { mode: \"chat\" },\n }),\n );\n sendToAgentChat({\n message: newPrompt.trim(),\n context: `The user wants to create a new automation. Scope: ${newScope}. Use manage-automations with action=define to create it. Ask clarifying questions if needed about what event to trigger on, conditions, and what actions to take.`,\n submit: true,\n newTab: true,\n });\n setNewPrompt(\"\");\n setNewOpen(false);\n },\n [newPrompt, newScope],\n );\n\n if (error) {\n return (\n <p className=\"text-[10px] text-red-500\">\n Failed to load automations: {error}\n </p>\n );\n }\n\n if (loading) {\n return (\n <div className=\"flex items-center gap-1.5 text-[10px] text-muted-foreground\">\n <IconLoader2 size={10} className=\"animate-spin\" />\n Loading...\n </div>\n );\n }\n\n return (\n <div className=\"space-y-2\">\n <div className=\"flex items-center gap-1.5\">\n <div className=\"relative\">\n <button\n ref={newButtonRef}\n type=\"button\"\n onClick={() => setNewOpen(!newOpen)}\n className=\"inline-flex items-center gap-1 rounded border border-border px-2 py-1 text-[10px] font-medium text-muted-foreground hover:text-foreground hover:bg-accent/40\"\n >\n <IconPlus size={10} />\n New Automation\n </button>\n {newOpen && (\n <div\n ref={newPopoverRef}\n className=\"absolute left-0 top-full mt-1.5 z-[220] w-72 rounded-lg border border-border bg-popover p-3 shadow-lg\"\n >\n <form onSubmit={handleNewSubmit}>\n <textarea\n value={newPrompt}\n onChange={(e) => setNewPrompt(e.target.value)}\n placeholder=\"Describe what you want to automate...\"\n className=\"w-full resize-y rounded-md border border-border bg-background px-2.5 py-2 text-[12px] text-foreground outline-none placeholder:text-muted-foreground/50 focus:ring-1 focus:ring-ring/50 min-h-[100px]\"\n autoFocus\n required\n onKeyDown={(e) => {\n if ((e.metaKey || e.ctrlKey) && e.key === \"Enter\") {\n e.preventDefault();\n if (newPrompt.trim()) handleNewSubmit(e);\n }\n }}\n />\n <div className=\"mt-2\">\n <select\n value={newScope}\n onChange={(e) =>\n setNewScope(e.target.value as \"personal\" | \"organization\")\n }\n className=\"w-full rounded-md border border-input bg-background px-3 py-1.5 text-[12px] text-foreground\"\n >\n <option value=\"personal\">Personal</option>\n <option value=\"organization\">Organization</option>\n </select>\n </div>\n <div className=\"mt-2.5 flex justify-end\">\n <button\n type=\"submit\"\n disabled={!newPrompt.trim()}\n className=\"rounded-md bg-primary px-3 py-1.5 text-[11px] font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n Create\n </button>\n </div>\n </form>\n </div>\n )}\n </div>\n <button\n type=\"button\"\n onClick={handleFireTestEvent}\n className=\"inline-flex items-center gap-1 rounded border border-border px-2 py-1 text-[10px] font-medium text-muted-foreground hover:text-foreground hover:bg-accent/40\"\n >\n <IconPlayerPlay size={10} />\n Fire Test Event\n </button>\n </div>\n\n {automations.length === 0 ? (\n <p className=\"text-[10px] text-muted-foreground\">\n No automations yet. Click \"New Automation\" to create one, or ask the\n agent to set up a scheduled or event-triggered task.\n </p>\n ) : (\n automations.map((item) => (\n <div\n key={item.id}\n className=\"rounded-md border border-border px-2.5 py-2 bg-accent/30\"\n >\n <div className=\"flex items-center justify-between gap-2\">\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center gap-1.5\">\n <span className=\"text-muted-foreground shrink-0\">\n {item.schedule ? (\n <IconClock size={11} />\n ) : (\n <IconBolt size={11} />\n )}\n </span>\n <span className=\"text-[11px] font-medium text-foreground truncate capitalize\">\n {item.name}\n </span>\n </div>\n {item.scheduleDescription && (\n <p className=\"text-[10px] text-muted-foreground mt-0.5 ml-[17px]\">\n {item.scheduleDescription}\n </p>\n )}\n {item.schedule && !item.scheduleDescription && (\n <p className=\"text-[10px] text-muted-foreground mt-0.5 ml-[17px] font-mono\">\n {item.schedule}\n </p>\n )}\n </div>\n <div className=\"flex items-center gap-1.5 shrink-0\">\n <StatusBadge status={item.lastStatus} />\n <button\n type=\"button\"\n onClick={() => handleToggle(item)}\n disabled={togglingId === item.id}\n className={`rounded px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide ${\n item.enabled\n ? \"bg-green-500/15 text-green-500\"\n : \"bg-accent/60 text-muted-foreground\"\n } hover:opacity-80 disabled:opacity-40`}\n title={item.enabled ? \"Disable\" : \"Enable\"}\n >\n {togglingId === item.id ? (\n <IconLoader2 size={10} className=\"animate-spin\" />\n ) : item.enabled ? (\n \"On\"\n ) : (\n \"Off\"\n )}\n </button>\n {confirmDeleteId === item.id ? (\n <div className=\"flex items-center gap-1\">\n <button\n type=\"button\"\n onClick={() => handleDelete(item)}\n disabled={deletingId === item.id}\n className=\"rounded px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide bg-red-500/15 text-red-500 hover:bg-red-500/25 disabled:opacity-40\"\n >\n {deletingId === item.id ? (\n <IconLoader2 size={10} className=\"animate-spin\" />\n ) : (\n \"Confirm\"\n )}\n </button>\n <button\n type=\"button\"\n onClick={() => setConfirmDeleteId(null)}\n className=\"rounded px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide bg-accent/60 text-muted-foreground hover:text-foreground\"\n >\n Cancel\n </button>\n </div>\n ) : (\n <button\n type=\"button\"\n onClick={() => setConfirmDeleteId(item.id)}\n className=\"text-muted-foreground hover:text-red-500 disabled:opacity-40\"\n title=\"Delete\"\n >\n <IconTrash size={12} />\n </button>\n )}\n </div>\n </div>\n {item.lastRun && (\n <p className=\"text-[10px] text-muted-foreground mt-1 ml-[17px]\">\n Last run:{\" \"}\n {new Date(item.lastRun).toLocaleString(undefined, {\n month: \"short\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"2-digit\",\n })}\n </p>\n )}\n </div>\n ))\n )}\n\n {toast && (\n <p\n className={`text-[10px] ${toast.kind === \"ok\" ? \"text-green-500\" : \"text-red-500\"}`}\n >\n {toast.text}\n </p>\n )}\n </div>\n );\n}\n\nfunction StatusBadge({ status }: { status?: string }) {\n if (!status) return null;\n\n const styles: Record<string, string> = {\n success: \"bg-green-500/15 text-green-500\",\n error: \"bg-red-500/15 text-red-500\",\n running: \"bg-blue-500/15 text-blue-500\",\n skipped: \"bg-accent/60 text-muted-foreground\",\n };\n\n return (\n <span\n className={`rounded-full px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide ${styles[status] ?? styles.skipped}`}\n >\n {status}\n </span>\n );\n}\n"]}
1
+ {"version":3,"file":"AutomationsSection.js","sourceRoot":"","sources":["../../../src/client/settings/AutomationsSection.tsx"],"names":[],"mappings":"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","sourcesContent":["import { agentNativePath } from \"../api-path.js\";\nimport React, { useEffect, useState, useCallback, useRef } from \"react\";\nimport {\n IconBolt,\n IconClock,\n IconLoader2,\n IconPlayerPlay,\n IconPlus,\n IconTrash,\n} from \"@tabler/icons-react\";\nimport { sendToAgentChat } from \"../agent-chat.js\";\n\ninterface TreeNode {\n name: string;\n path: string;\n type: \"file\" | \"folder\";\n kind?: string;\n children?: TreeNode[];\n resource?: {\n id: string;\n path: string;\n owner: string;\n mimeType: string;\n size: number;\n createdAt: number;\n updatedAt: number;\n };\n jobMeta?: {\n schedule?: string;\n scheduleDescription?: string;\n enabled?: boolean;\n lastStatus?: string;\n lastRun?: string;\n nextRun?: string;\n };\n}\n\ninterface AutomationItem {\n id: string;\n name: string;\n path: string;\n schedule?: string;\n scheduleDescription?: string;\n enabled: boolean;\n lastStatus?: string;\n lastRun?: string;\n nextRun?: string;\n}\n\nfunction flattenJobs(nodes: TreeNode[]): AutomationItem[] {\n const items: AutomationItem[] = [];\n for (const node of nodes) {\n if (node.type === \"folder\" && node.children) {\n items.push(...flattenJobs(node.children));\n }\n if (\n node.type === \"file\" &&\n node.kind === \"job\" &&\n node.resource &&\n node.jobMeta\n ) {\n const name = node.name.replace(/\\.md$/, \"\").replace(/-/g, \" \");\n items.push({\n id: node.resource.id,\n name,\n path: node.resource.path,\n schedule: node.jobMeta.schedule,\n scheduleDescription: node.jobMeta.scheduleDescription,\n enabled: node.jobMeta.enabled ?? false,\n lastStatus: node.jobMeta.lastStatus,\n lastRun: node.jobMeta.lastRun,\n nextRun: node.jobMeta.nextRun,\n });\n }\n }\n return items;\n}\n\nexport function AutomationsSection() {\n const [automations, setAutomations] = useState<AutomationItem[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [togglingId, setTogglingId] = useState<string | null>(null);\n const [deletingId, setDeletingId] = useState<string | null>(null);\n const [confirmDeleteId, setConfirmDeleteId] = useState<string | null>(null);\n const [toast, setToast] = useState<{\n kind: \"ok\" | \"err\";\n text: string;\n } | null>(null);\n const [reloadToken, setReloadToken] = useState(0);\n\n const showToast = useCallback(\n (kind: \"ok\" | \"err\", text: string, ms = 2500) => {\n setToast({ kind, text });\n setTimeout(() => setToast(null), ms);\n },\n [],\n );\n\n useEffect(() => {\n let cancelled = false;\n setLoading(true);\n fetch(agentNativePath(\"/_agent-native/resources/tree\"))\n .then(async (r) => {\n if (!r.ok) throw new Error(`Failed to load (${r.status})`);\n return (await r.json()) as { tree: TreeNode[] };\n })\n .then(({ tree }) => {\n if (cancelled) return;\n const jobsFolder = tree.find(\n (n) => n.name === \"jobs\" && n.type === \"folder\",\n );\n const items = jobsFolder?.children\n ? flattenJobs(jobsFolder.children)\n : [];\n setAutomations(items);\n setLoading(false);\n })\n .catch((err) => {\n if (cancelled) return;\n setError(err?.message ?? \"Failed to load\");\n setLoading(false);\n });\n return () => {\n cancelled = true;\n };\n }, [reloadToken]);\n\n const reload = useCallback(() => setReloadToken((t) => t + 1), []);\n\n const handleToggle = useCallback(\n async (item: AutomationItem) => {\n setTogglingId(item.id);\n try {\n const res = await fetch(\n agentNativePath(\n `/_agent-native/resources/${encodeURIComponent(item.id)}`,\n ),\n );\n if (!res.ok) {\n showToast(\"err\", \"Failed to read automation\");\n return;\n }\n const resource = await res.json();\n const content: string = resource.content ?? \"\";\n\n const newEnabled = !item.enabled;\n const updated = content.replace(\n /^(enabled:\\s*)(true|false)/m,\n `$1${newEnabled}`,\n );\n\n const putRes = await fetch(\n agentNativePath(\n `/_agent-native/resources/${encodeURIComponent(item.id)}`,\n ),\n {\n method: \"PUT\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ content: updated }),\n },\n );\n if (!putRes.ok) {\n showToast(\"err\", \"Failed to update automation\");\n return;\n }\n showToast(\"ok\", newEnabled ? \"Enabled\" : \"Disabled\");\n reload();\n } finally {\n setTogglingId(null);\n }\n },\n [reload, showToast],\n );\n\n const handleDelete = useCallback(\n async (item: AutomationItem) => {\n setDeletingId(item.id);\n try {\n const res = await fetch(\n agentNativePath(\n `/_agent-native/resources/${encodeURIComponent(item.id)}`,\n ),\n {\n method: \"DELETE\",\n headers: { \"Content-Type\": \"application/json\" },\n },\n );\n if (!res.ok) {\n showToast(\"err\", \"Failed to delete automation\");\n return;\n }\n showToast(\"ok\", \"Deleted\");\n setConfirmDeleteId(null);\n reload();\n } finally {\n setDeletingId(null);\n }\n },\n [reload, showToast],\n );\n\n const handleFireTestEvent = useCallback(async () => {\n showToast(\"ok\", \"Firing test event...\");\n try {\n const res = await fetch(\n agentNativePath(\"/_agent-native/automations/fire-test\"),\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ data: {} }),\n },\n );\n if (!res.ok) {\n showToast(\"err\", `Failed to fire event (${res.status})`);\n return;\n }\n showToast(\"ok\", \"Event fired\");\n } catch (err: any) {\n showToast(\"err\", err?.message ?? \"Failed to fire event\");\n }\n }, [showToast]);\n\n const [newOpen, setNewOpen] = useState(false);\n const [newPrompt, setNewPrompt] = useState(\"\");\n const [newScope, setNewScope] = useState<\"personal\" | \"organization\">(\n \"personal\",\n );\n const newPopoverRef = useRef<HTMLDivElement>(null);\n const newButtonRef = useRef<HTMLButtonElement>(null);\n\n // Close popover on outside click\n useEffect(() => {\n if (!newOpen) return;\n function handleClick(e: MouseEvent) {\n if (\n newPopoverRef.current &&\n !newPopoverRef.current.contains(e.target as Node) &&\n newButtonRef.current &&\n !newButtonRef.current.contains(e.target as Node)\n ) {\n setNewOpen(false);\n }\n }\n document.addEventListener(\"mousedown\", handleClick);\n return () => document.removeEventListener(\"mousedown\", handleClick);\n }, [newOpen]);\n\n // Close popover on Escape\n useEffect(() => {\n if (!newOpen) return;\n function handleKey(e: KeyboardEvent) {\n if (e.key === \"Escape\") setNewOpen(false);\n }\n document.addEventListener(\"keydown\", handleKey);\n return () => document.removeEventListener(\"keydown\", handleKey);\n }, [newOpen]);\n\n const handleNewSubmit = useCallback(\n (e: React.FormEvent) => {\n e.preventDefault();\n if (!newPrompt.trim()) return;\n window.dispatchEvent(\n new CustomEvent(\"agent-panel:set-mode\", {\n detail: { mode: \"chat\" },\n }),\n );\n sendToAgentChat({\n message: newPrompt.trim(),\n context: `The user wants to create a new automation. Scope: ${newScope}. Use manage-automations with action=define to create it. Ask clarifying questions if needed about what event to trigger on, conditions, and what actions to take.`,\n submit: true,\n newTab: true,\n });\n setNewPrompt(\"\");\n setNewOpen(false);\n },\n [newPrompt, newScope],\n );\n\n if (error) {\n return (\n <p className=\"text-[10px] text-red-500\">\n Failed to load automations: {error}\n </p>\n );\n }\n\n if (loading) {\n return (\n <div className=\"flex items-center gap-1.5 text-[10px] text-muted-foreground\">\n <IconLoader2 size={10} className=\"animate-spin\" />\n Loading...\n </div>\n );\n }\n\n return (\n <div className=\"space-y-2\">\n <div className=\"flex items-center gap-1.5\">\n <div className=\"relative\">\n <button\n ref={newButtonRef}\n type=\"button\"\n onClick={() => setNewOpen(!newOpen)}\n className=\"inline-flex items-center gap-1 rounded border border-border px-2 py-1 text-[10px] font-medium text-muted-foreground hover:text-foreground hover:bg-accent/40\"\n >\n <IconPlus size={10} />\n New Automation\n </button>\n {newOpen && (\n <div\n ref={newPopoverRef}\n className=\"absolute left-0 top-full mt-1.5 z-[220] w-72 rounded-lg border border-border bg-popover p-3 shadow-lg\"\n >\n <form onSubmit={handleNewSubmit} className=\"space-y-2.5\">\n <p className=\"text-sm font-semibold text-foreground\">\n New automation\n </p>\n <textarea\n value={newPrompt}\n onChange={(e) => setNewPrompt(e.target.value)}\n placeholder=\"Describe what you want to automate...\"\n className=\"w-full resize-y rounded-md border border-border bg-background px-2.5 py-2 text-[12px] text-foreground outline-none placeholder:text-muted-foreground/50 focus:ring-1 focus:ring-ring/50 min-h-[100px]\"\n autoFocus\n required\n onKeyDown={(e) => {\n if ((e.metaKey || e.ctrlKey) && e.key === \"Enter\") {\n e.preventDefault();\n if (newPrompt.trim()) handleNewSubmit(e);\n }\n }}\n />\n <div>\n <select\n value={newScope}\n onChange={(e) =>\n setNewScope(e.target.value as \"personal\" | \"organization\")\n }\n className=\"w-full rounded-md border border-input bg-background px-3 py-1.5 text-[12px] text-foreground\"\n >\n <option value=\"personal\">Personal</option>\n <option value=\"organization\">Organization</option>\n </select>\n </div>\n <div className=\"flex items-center justify-end gap-2\">\n <span className=\"text-[11px] text-muted-foreground/70\">\n {/Mac|iPhone|iPad/.test(navigator.userAgent) ? \"⌘\" : \"Ctrl\"}\n +Enter to submit\n </span>\n <button\n type=\"submit\"\n disabled={!newPrompt.trim()}\n className=\"rounded-md bg-primary px-3 py-1.5 text-[11px] font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n Create\n </button>\n </div>\n </form>\n </div>\n )}\n </div>\n <button\n type=\"button\"\n onClick={handleFireTestEvent}\n className=\"inline-flex items-center gap-1 rounded border border-border px-2 py-1 text-[10px] font-medium text-muted-foreground hover:text-foreground hover:bg-accent/40\"\n >\n <IconPlayerPlay size={10} />\n Fire Test Event\n </button>\n </div>\n\n {automations.length === 0 ? (\n <p className=\"text-[10px] text-muted-foreground\">\n No automations yet. Click \"New Automation\" to create one, or ask the\n agent to set up a scheduled or event-triggered task.\n </p>\n ) : (\n automations.map((item) => (\n <div\n key={item.id}\n className=\"rounded-md border border-border px-2.5 py-2 bg-accent/30\"\n >\n <div className=\"flex items-center justify-between gap-2\">\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center gap-1.5\">\n <span className=\"text-muted-foreground shrink-0\">\n {item.schedule ? (\n <IconClock size={11} />\n ) : (\n <IconBolt size={11} />\n )}\n </span>\n <span className=\"text-[11px] font-medium text-foreground truncate capitalize\">\n {item.name}\n </span>\n </div>\n {item.scheduleDescription && (\n <p className=\"text-[10px] text-muted-foreground mt-0.5 ml-[17px]\">\n {item.scheduleDescription}\n </p>\n )}\n {item.schedule && !item.scheduleDescription && (\n <p className=\"text-[10px] text-muted-foreground mt-0.5 ml-[17px] font-mono\">\n {item.schedule}\n </p>\n )}\n </div>\n <div className=\"flex items-center gap-1.5 shrink-0\">\n <StatusBadge status={item.lastStatus} />\n <button\n type=\"button\"\n onClick={() => handleToggle(item)}\n disabled={togglingId === item.id}\n className={`rounded px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide ${\n item.enabled\n ? \"bg-green-500/15 text-green-500\"\n : \"bg-accent/60 text-muted-foreground\"\n } hover:opacity-80 disabled:opacity-40`}\n title={item.enabled ? \"Disable\" : \"Enable\"}\n >\n {togglingId === item.id ? (\n <IconLoader2 size={10} className=\"animate-spin\" />\n ) : item.enabled ? (\n \"On\"\n ) : (\n \"Off\"\n )}\n </button>\n {confirmDeleteId === item.id ? (\n <div className=\"flex items-center gap-1\">\n <button\n type=\"button\"\n onClick={() => handleDelete(item)}\n disabled={deletingId === item.id}\n className=\"rounded px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide bg-red-500/15 text-red-500 hover:bg-red-500/25 disabled:opacity-40\"\n >\n {deletingId === item.id ? (\n <IconLoader2 size={10} className=\"animate-spin\" />\n ) : (\n \"Confirm\"\n )}\n </button>\n <button\n type=\"button\"\n onClick={() => setConfirmDeleteId(null)}\n className=\"rounded px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide bg-accent/60 text-muted-foreground hover:text-foreground\"\n >\n Cancel\n </button>\n </div>\n ) : (\n <button\n type=\"button\"\n onClick={() => setConfirmDeleteId(item.id)}\n className=\"text-muted-foreground hover:text-red-500 disabled:opacity-40\"\n title=\"Delete\"\n >\n <IconTrash size={12} />\n </button>\n )}\n </div>\n </div>\n {item.lastRun && (\n <p className=\"text-[10px] text-muted-foreground mt-1 ml-[17px]\">\n Last run:{\" \"}\n {new Date(item.lastRun).toLocaleString(undefined, {\n month: \"short\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"2-digit\",\n })}\n </p>\n )}\n </div>\n ))\n )}\n\n {toast && (\n <p\n className={`text-[10px] ${toast.kind === \"ok\" ? \"text-green-500\" : \"text-red-500\"}`}\n >\n {toast.text}\n </p>\n )}\n </div>\n );\n}\n\nfunction StatusBadge({ status }: { status?: string }) {\n if (!status) return null;\n\n const styles: Record<string, string> = {\n success: \"bg-green-500/15 text-green-500\",\n error: \"bg-red-500/15 text-red-500\",\n running: \"bg-blue-500/15 text-blue-500\",\n skipped: \"bg-accent/60 text-muted-foreground\",\n };\n\n return (\n <span\n className={`rounded-full px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide ${styles[status] ?? styles.skipped}`}\n >\n {status}\n </span>\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"VoiceTranscriptionSection.d.ts","sourceRoot":"","sources":["../../../src/client/settings/VoiceTranscriptionSection.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAwCH,wBAAgB,yBAAyB,4CAuQxC;AAuED,wBAAgB,sBAAsB,4CAErC"}
1
+ {"version":3,"file":"VoiceTranscriptionSection.d.ts","sourceRoot":"","sources":["../../../src/client/settings/VoiceTranscriptionSection.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA0DH,wBAAgB,yBAAyB,4CAuTxC;AAuED,wBAAgB,sBAAsB,4CAErC"}