agent-relay-server 0.57.0 → 0.57.1
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.
- package/docs/openapi.json +1 -1
- package/package.json +1 -1
- package/public/assets/{MessageBubble-DmZIqnga.js → MessageBubble-BqFAi9gS.js} +2 -2
- package/public/assets/{MessageBubble-DmZIqnga.js.map → MessageBubble-BqFAi9gS.js.map} +1 -1
- package/public/assets/{PlanGraphPanel-DpTMkCBs.js → PlanGraphPanel-CJROpj66.js} +2 -2
- package/public/assets/{PlanGraphPanel-DpTMkCBs.js.map → PlanGraphPanel-CJROpj66.js.map} +1 -1
- package/public/assets/{activity-D_3n1maA.js → activity-D2m3VCXV.js} +2 -2
- package/public/assets/{activity-D_3n1maA.js.map → activity-D2m3VCXV.js.map} +1 -1
- package/public/assets/{agent-profiles-Bp-KhfLJ.js → agent-profiles-CIf4b1V7.js} +2 -2
- package/public/assets/{agent-profiles-Bp-KhfLJ.js.map → agent-profiles-CIf4b1V7.js.map} +1 -1
- package/public/assets/{agents-CHG09FED.js → agents-lDwoWazM.js} +2 -2
- package/public/assets/{agents-CHG09FED.js.map → agents-lDwoWazM.js.map} +1 -1
- package/public/assets/{analytics-DadE7J8c.js → analytics-OsZ2HJxy.js} +2 -2
- package/public/assets/{analytics-DadE7J8c.js.map → analytics-OsZ2HJxy.js.map} +1 -1
- package/public/assets/{automation-Da7hPlwY.js → automation-4eeiOl19.js} +2 -2
- package/public/assets/{automation-Da7hPlwY.js.map → automation-4eeiOl19.js.map} +1 -1
- package/public/assets/{branch-state-badge-BIFdTVFP.js → branch-state-badge-B9WqTxZJ.js} +2 -2
- package/public/assets/{branch-state-badge-BIFdTVFP.js.map → branch-state-badge-B9WqTxZJ.js.map} +1 -1
- package/public/assets/{channels-CTkaNTj3.js → channels-HK6sLYpZ.js} +2 -2
- package/public/assets/{channels-CTkaNTj3.js.map → channels-HK6sLYpZ.js.map} +1 -1
- package/public/assets/{chat-EaifCGGe.js → chat-B9FJi94P.js} +2 -2
- package/public/assets/{chat-EaifCGGe.js.map → chat-B9FJi94P.js.map} +1 -1
- package/public/assets/{connectors-CIMZt48i.js → connectors-3mMNW4Qk.js} +2 -2
- package/public/assets/{connectors-CIMZt48i.js.map → connectors-3mMNW4Qk.js.map} +1 -1
- package/public/assets/{display-D6H3VZ53.js → display-CketawEF.js} +2 -2
- package/public/assets/{display-D6H3VZ53.js.map → display-CketawEF.js.map} +1 -1
- package/public/assets/{formatted-body-impl-CDwuhxYD.js → formatted-body-impl-BOLz9dDs.js} +2 -2
- package/public/assets/{formatted-body-impl-CDwuhxYD.js.map → formatted-body-impl-BOLz9dDs.js.map} +1 -1
- package/public/assets/{index-DG_cFJIA.js → index-0rOVZ5nm.js} +6 -6
- package/public/assets/{index-DG_cFJIA.js.map → index-0rOVZ5nm.js.map} +1 -1
- package/public/assets/{insights-DqaWxMEv.js → insights-DwtSIqYc.js} +2 -2
- package/public/assets/{insights-DqaWxMEv.js.map → insights-DwtSIqYc.js.map} +1 -1
- package/public/assets/{integrations-g0NS0UqB.js → integrations-Dd6haLpy.js} +2 -2
- package/public/assets/{integrations-g0NS0UqB.js.map → integrations-Dd6haLpy.js.map} +1 -1
- package/public/assets/{maintenance-B1ipDm3t.js → maintenance-DVzbjn4x.js} +2 -2
- package/public/assets/{maintenance-B1ipDm3t.js.map → maintenance-DVzbjn4x.js.map} +1 -1
- package/public/assets/{managed-agents-DHft-J93.js → managed-agents-CJXaWFgZ.js} +2 -2
- package/public/assets/{managed-agents-DHft-J93.js.map → managed-agents-CJXaWFgZ.js.map} +1 -1
- package/public/assets/{markdown-preview-impl-Dk0jta-N.js → markdown-preview-impl-CCoHxXmF.js} +2 -2
- package/public/assets/{markdown-preview-impl-Dk0jta-N.js.map → markdown-preview-impl-CCoHxXmF.js.map} +1 -1
- package/public/assets/{memory-Cc_14vr4.js → memory-f9IAAOSG.js} +2 -2
- package/public/assets/{memory-Cc_14vr4.js.map → memory-f9IAAOSG.js.map} +1 -1
- package/public/assets/{messages-gSUwhZbt.js → messages-DuSBSnsM.js} +2 -2
- package/public/assets/{messages-gSUwhZbt.js.map → messages-DuSBSnsM.js.map} +1 -1
- package/public/assets/{orchestrators-D7RL2Vdm.js → orchestrators-BUCE7jk3.js} +2 -2
- package/public/assets/{orchestrators-D7RL2Vdm.js.map → orchestrators-BUCE7jk3.js.map} +1 -1
- package/public/assets/{overview-PP2eD4_Y.js → overview-B0_IOXOo.js} +2 -2
- package/public/assets/{overview-PP2eD4_Y.js.map → overview-B0_IOXOo.js.map} +1 -1
- package/public/assets/{pairs-DhF9MXdu.js → pairs-DdA8n3dX.js} +2 -2
- package/public/assets/{pairs-DhF9MXdu.js.map → pairs-DdA8n3dX.js.map} +1 -1
- package/public/assets/{security-CwMaW5CQ.js → security-07gu7r1C.js} +2 -2
- package/public/assets/{security-CwMaW5CQ.js.map → security-07gu7r1C.js.map} +1 -1
- package/public/assets/{select-CifGD5oc.js → select-CLQutzAh.js} +2 -2
- package/public/assets/{select-CifGD5oc.js.map → select-CLQutzAh.js.map} +1 -1
- package/public/assets/{settings-Cc8EgRR7.js → settings-E4QJiNjt.js} +2 -2
- package/public/assets/{settings-Cc8EgRR7.js.map → settings-E4QJiNjt.js.map} +1 -1
- package/public/assets/{store-DKtaJZyC.js → store-DmxnYVm1.js} +2 -2
- package/public/assets/{store-DKtaJZyC.js.map → store-DmxnYVm1.js.map} +1 -1
- package/public/assets/{tasks-Boji1e5w.js → tasks-BB1nTWjm.js} +2 -2
- package/public/assets/{tasks-Boji1e5w.js.map → tasks-BB1nTWjm.js.map} +1 -1
- package/public/assets/{teams-DJVSjs4x.js → teams-BtY2fi5X.js} +2 -2
- package/public/assets/{teams-DJVSjs4x.js.map → teams-BtY2fi5X.js.map} +1 -1
- package/public/assets/{terminal-viewer-impl-DdbGJg-X.js → terminal-viewer-impl-CHCUDXgj.js} +2 -2
- package/public/assets/{terminal-viewer-impl-DdbGJg-X.js.map → terminal-viewer-impl-CHCUDXgj.js.map} +1 -1
- package/public/assets/{work-queue-BKsEKdR7.js → work-queue-CPXo2IdX.js} +2 -2
- package/public/assets/{work-queue-BKsEKdR7.js.map → work-queue-CPXo2IdX.js.map} +1 -1
- package/public/assets/{workspaces-BTJ2O87P.js → workspaces-D_vNXWDf.js} +2 -2
- package/public/assets/{workspaces-BTJ2O87P.js.map → workspaces-D_vNXWDf.js.map} +1 -1
- package/public/index.html +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings-Cc8EgRR7.js","names":[],"sources":["../../dashboard/src/components/views/settings.tsx"],"sourcesContent":["import { useEffect, useState } from 'react'\nimport { api } from '@/lib/api'\nimport { useRelayStore } from '@/store'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport { Textarea } from '@/components/ui/textarea'\nimport { Switch } from '@/components/ui/switch'\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'\nimport { KOKORO_VOICES, availableSpeechVoices } from '@/lib/voice'\nimport { Brain, FolderSymlink, GitMerge, GitPullRequest, Save, Terminal, TestTube2, Volume2 } from 'lucide-react'\n\ntype ProviderName = 'claude' | 'codex'\n\ninterface ProviderConfig {\n command: string\n defaultArgs: string[]\n env: Record<string, string>\n pluginDirs: string[]\n defaultCapabilities: string[]\n defaultApprovalMode: string\n defaultTags: string[]\n chatCaptureMode: 'final' | 'full'\n headless: {\n tmuxPrefix: string\n shutdownTimeoutMs: number\n }\n}\n\nconst providers: ProviderName[] = ['claude', 'codex']\n\nexport function SettingsView() {\n const [configs, setConfigs] = useState<Record<string, ProviderConfig>>({})\n const [selected, setSelected] = useState<ProviderName>('claude')\n const [status, setStatus] = useState('')\n\n useEffect(() => {\n api<Record<string, ProviderConfig>>('GET', '/providers/config')\n .then(setConfigs)\n .catch((e) => setStatus((e as Error).message))\n }, [])\n\n const config = configs[selected]\n const update = (patch: Partial<ProviderConfig>) => {\n if (!config) return\n setConfigs({ ...configs, [selected]: { ...config, ...patch } })\n }\n\n async function save() {\n if (!config) return\n const saved = await api<ProviderConfig>('PUT', `/providers/${selected}/config`, config)\n setConfigs({ ...configs, [selected]: saved })\n setStatus(`${selected} saved`)\n }\n\n async function test() {\n const result = await api<{ ok: boolean; path?: string; error?: string }>('POST', `/providers/${selected}/config/test`)\n setStatus(result.ok ? `${selected} command: ${result.path || 'found'}` : result.error || 'command not found')\n }\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between gap-3\">\n <div>\n <h1 className=\"text-xl font-semibold\">Settings</h1>\n <p className=\"text-sm text-muted-foreground\">Provider runner configuration</p>\n </div>\n <div className=\"flex gap-2\">\n {providers.map((provider) => (\n <Button key={provider} variant={selected === provider ? 'default' : 'outline'} onClick={() => setSelected(provider)}>\n <Terminal className=\"w-4 h-4\" />{provider}\n </Button>\n ))}\n </div>\n </div>\n\n {config && (\n <div className=\"grid gap-4 lg:grid-cols-[minmax(0,1fr)_minmax(280px,360px)]\">\n <section className=\"space-y-3\">\n <Field label=\"Command\">\n <Input value={config.command} onChange={(e) => update({ command: e.target.value })} />\n </Field>\n <Field label=\"Default arguments\">\n <Textarea rows={3} value={config.defaultArgs.join('\\n')} onChange={(e) => update({ defaultArgs: lines(e.target.value) })} />\n </Field>\n <Field label=\"Plugin directories\">\n <Textarea rows={3} value={config.pluginDirs.join('\\n')} onChange={(e) => update({ pluginDirs: lines(e.target.value) })} />\n </Field>\n <Field label=\"Environment\">\n <Textarea rows={5} value={recordLines(config.env)} onChange={(e) => update({ env: parseRecordLines(e.target.value) })} />\n </Field>\n </section>\n\n <section className=\"space-y-3\">\n <Field label=\"Capabilities\">\n <Textarea rows={3} value={config.defaultCapabilities.join('\\n')} onChange={(e) => update({ defaultCapabilities: lines(e.target.value) })} />\n </Field>\n <Field label=\"Tags\">\n <Textarea rows={3} value={config.defaultTags.join('\\n')} onChange={(e) => update({ defaultTags: lines(e.target.value) })} />\n </Field>\n <Field label=\"Approval mode\">\n <Input value={config.defaultApprovalMode} onChange={(e) => update({ defaultApprovalMode: e.target.value })} />\n </Field>\n <Field label=\"Chat capture mode\">\n <Select value={config.chatCaptureMode ?? 'final'} onValueChange={(v) => update({ chatCaptureMode: v as 'final' | 'full' })}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"final\">Final response only</SelectItem>\n <SelectItem value=\"full\">Full turn (intermediate messages)</SelectItem>\n </SelectContent>\n </Select>\n </Field>\n <Field label=\"tmux prefix\">\n <Input value={config.headless.tmuxPrefix} onChange={(e) => update({ headless: { ...config.headless, tmuxPrefix: e.target.value } })} />\n </Field>\n <Field label=\"Shutdown timeout\">\n <Input type=\"number\" value={config.headless.shutdownTimeoutMs} onChange={(e) => update({ headless: { ...config.headless, shutdownTimeoutMs: Number(e.target.value) || 10000 } })} />\n </Field>\n <div className=\"flex gap-2 pt-2\">\n <Button onClick={save}><Save className=\"w-4 h-4\" />Save</Button>\n <Button variant=\"outline\" onClick={test}><TestTube2 className=\"w-4 h-4\" />Test</Button>\n </div>\n {status && <p className=\"text-sm text-muted-foreground\">{status}</p>}\n </section>\n </div>\n )}\n\n <ChatDisplaySettings />\n\n <WorkspaceSettings />\n\n <LandingSettings />\n\n <StewardSettings />\n\n <VoiceSettings />\n </div>\n )\n}\n\ninterface WorkspaceConfig {\n symlinkPaths: string[]\n}\n\nconst DEFAULT_WORKSPACE: WorkspaceConfig = { symlinkPaths: [] }\n\n// Global isolated-worktree provisioning (#159 follow-up). A fresh git worktree only has\n// git-tracked files; node_modules are symlinked automatically and these extra untracked\n// paths are too. Only links what actually exists in main — missing entries are ignored.\nfunction WorkspaceSettings() {\n const [config, setConfig] = useState<WorkspaceConfig>(DEFAULT_WORKSPACE)\n const [status, setStatus] = useState('')\n\n useEffect(() => {\n api<{ value: WorkspaceConfig }>('GET', '/workspace-config')\n .then((entry) => setConfig({ ...DEFAULT_WORKSPACE, ...entry.value }))\n .catch((e) => setStatus((e as Error).message))\n }, [])\n\n async function save() {\n try {\n const saved = await api<{ value: WorkspaceConfig }>('PUT', '/workspace-config', config)\n setConfig({ ...DEFAULT_WORKSPACE, ...saved.value })\n setStatus('Workspace config saved')\n } catch (e) {\n setStatus((e as Error).message)\n }\n }\n\n return (\n <section className=\"space-y-3 rounded-lg border p-4\">\n <div className=\"flex items-center gap-2\">\n <FolderSymlink className=\"w-4 h-4\" />\n <div>\n <h2 className=\"text-sm font-semibold\">Isolated worktree symlinks</h2>\n <p className=\"text-xs text-muted-foreground\">\n Untracked files or filename patterns symlinked from main into each isolated worktree (the "Workspace" spawn option), one per line. Plain names like <code>AGENTS.md</code> or <code>.claude-rig</code> match files and directories; entries with <code>*?[]{'{}'}</code> are expanded as globs. A path is only linked if it exists in main.\n </p>\n </div>\n </div>\n <Field label=\"Paths / patterns\">\n <Textarea\n rows={5}\n placeholder={'AGENTS.md\\n.claude-rig'}\n value={config.symlinkPaths.join('\\n')}\n onChange={(e) => setConfig({ ...config, symlinkPaths: lines(e.target.value) })}\n />\n </Field>\n <div className=\"flex items-center gap-2 pt-1\">\n <Button onClick={save}><Save className=\"w-4 h-4\" />Save</Button>\n {status && <p className=\"text-sm text-muted-foreground\">{status}</p>}\n </div>\n </section>\n )\n}\n\ntype LandingStrategy = 'direct' | 'pr'\n\ninterface LandingConfig {\n strategy: LandingStrategy\n}\n\ninterface ConfigEntry<T> {\n value: T\n}\n\nconst DEFAULT_LANDING: LandingConfig = { strategy: 'direct' }\n\nfunction LandingSettings() {\n const [config, setConfig] = useState<LandingConfig>(DEFAULT_LANDING)\n const [status, setStatus] = useState('')\n\n useEffect(() => {\n api<ConfigEntry<LandingConfig>>('GET', '/config/landing/default')\n .then((entry) => setConfig({ ...DEFAULT_LANDING, ...entry.value }))\n .catch((e) => {\n if ((e as { status?: number }).status === 404) {\n setConfig(DEFAULT_LANDING)\n return\n }\n setStatus((e as Error).message)\n })\n }, [])\n\n async function save() {\n try {\n const saved = await api<ConfigEntry<LandingConfig>>('PUT', '/config/landing/default', { value: config, updatedBy: 'dashboard' })\n setConfig({ ...DEFAULT_LANDING, ...saved.value })\n setStatus('Landing config saved')\n } catch (e) {\n setStatus((e as Error).message)\n }\n }\n\n return (\n <section className=\"space-y-3 rounded-lg border p-4\">\n <div className=\"flex items-center gap-2\">\n <GitPullRequest className=\"w-4 h-4\" />\n <div>\n <h2 className=\"text-sm font-semibold\">Branch landing</h2>\n <p className=\"text-xs text-muted-foreground\">Instance default for lands without an explicit strategy. PR opens a pull request and Relay auto-completes on green; direct merges straight to main.</p>\n </div>\n </div>\n\n <Field label=\"Branch landing strategy\">\n <Select value={config.strategy} onValueChange={(v) => setConfig({ strategy: v as LandingStrategy })}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"direct\">Direct</SelectItem>\n <SelectItem value=\"pr\">Pull request</SelectItem>\n </SelectContent>\n </Select>\n </Field>\n\n <div className=\"flex items-center gap-2 pt-1\">\n <Button onClick={save}><Save className=\"w-4 h-4\" />Save</Button>\n {status && <p className=\"text-sm text-muted-foreground\">{status}</p>}\n </div>\n </section>\n )\n}\n\n// Chat display: per-viewer rendering preferences for the Chat panel. These are\n// client-side (persisted in the browser), not provider config — toggling is instant\n// and retroactive. Reasoning steps are still captured by the runner; this only\n// controls whether they're shown. The agent's narration (the terminal's `●` lines)\n// is always shown.\nfunction ChatDisplaySettings() {\n const showReasoning = useRelayStore((s) => s.showReasoning)\n const set = useRelayStore((s) => s.set)\n return (\n <section className=\"space-y-3 rounded-lg border p-4\">\n <div className=\"flex items-center justify-between gap-2\">\n <div className=\"flex items-center gap-2\">\n <Brain className=\"w-4 h-4\" />\n <div>\n <h2 className=\"text-sm font-semibold\">Show reasoning details</h2>\n <p className=\"text-xs text-muted-foreground\">Show the agent's internal thinking inline in chat, alongside its narration and tool steps. Off by default — narration is always shown either way.</p>\n </div>\n </div>\n <Switch checked={showReasoning} onCheckedChange={(v) => set({ showReasoning: v })} />\n </div>\n </section>\n )\n}\n\n// Voice settings: TTS output (speak agent responses — engine + per-engine voice)\n// and the push-to-talk mic-input behaviour. TTS config used to live inline in the\n// chat header; it moved here to declutter the header (especially on mobile). The\n// header keeps only the speaker on/off toggle for quick muting.\nfunction VoiceSettings() {\n const voiceTtsEnabled = useRelayStore((s) => s.voiceTtsEnabled)\n const setVoiceTtsEnabled = useRelayStore((s) => s.setVoiceTtsEnabled)\n const voiceTtsMode = useRelayStore((s) => s.voiceTtsMode)\n const setVoiceTtsMode = useRelayStore((s) => s.setVoiceTtsMode)\n const voiceTtsKokoroVoice = useRelayStore((s) => s.voiceTtsKokoroVoice)\n const setVoiceTtsKokoroVoice = useRelayStore((s) => s.setVoiceTtsKokoroVoice)\n const voiceTtsBrowserVoice = useRelayStore((s) => s.voiceTtsBrowserVoice)\n const setVoiceTtsBrowserVoice = useRelayStore((s) => s.setVoiceTtsBrowserVoice)\n const voiceInputMode = useRelayStore((s) => s.voiceInputMode)\n const setVoiceInputMode = useRelayStore((s) => s.setVoiceInputMode)\n\n // External sync: the browser loads its speech voices asynchronously, so\n // re-read them when the engine signals the list changed.\n const [browserVoices, setBrowserVoices] = useState(() => availableSpeechVoices())\n useEffect(() => {\n if (typeof window === 'undefined' || !('speechSynthesis' in window)) return\n const refresh = () => setBrowserVoices(availableSpeechVoices())\n refresh()\n window.speechSynthesis.addEventListener?.('voiceschanged', refresh)\n return () => window.speechSynthesis.removeEventListener?.('voiceschanged', refresh)\n }, [])\n\n const kokoroOptions = KOKORO_VOICES.some((v) => v.id === voiceTtsKokoroVoice)\n ? KOKORO_VOICES\n : [...KOKORO_VOICES, { id: voiceTtsKokoroVoice, label: voiceTtsKokoroVoice }]\n\n return (\n <section className=\"space-y-3 rounded-lg border p-4\">\n <div className=\"flex items-center justify-between gap-2\">\n <div className=\"flex items-center gap-2\">\n <Volume2 className=\"w-4 h-4\" />\n <div>\n <h2 className=\"text-sm font-semibold\">Voice</h2>\n <p className=\"text-xs text-muted-foreground\">Speak agent responses aloud in the active chat, and how push-to-talk behaves.</p>\n </div>\n </div>\n <Switch checked={voiceTtsEnabled} onCheckedChange={setVoiceTtsEnabled} />\n </div>\n <Field label=\"Speech engine\">\n <Select value={voiceTtsMode} onValueChange={(v) => setVoiceTtsMode(v as 'kokoro' | 'browser')}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"kokoro\">Kokoro (server, natural — falls back to browser)</SelectItem>\n <SelectItem value=\"browser\">Browser (Web Speech API)</SelectItem>\n </SelectContent>\n </Select>\n </Field>\n <Field label=\"Kokoro voice\">\n <Select value={voiceTtsKokoroVoice} onValueChange={setVoiceTtsKokoroVoice}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n {kokoroOptions.map((v) => <SelectItem key={v.id} value={v.id}>{v.label}</SelectItem>)}\n </SelectContent>\n </Select>\n </Field>\n <Field label=\"Browser voice\">\n <Select value={voiceTtsBrowserVoice || '__default__'} onValueChange={(v) => setVoiceTtsBrowserVoice(v === '__default__' ? '' : v)}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"__default__\">System default</SelectItem>\n {browserVoices.map((v) => <SelectItem key={v.uri} value={v.uri}>{v.label}</SelectItem>)}\n </SelectContent>\n </Select>\n </Field>\n <Field label=\"Push-to-talk input\">\n <Select value={voiceInputMode} onValueChange={(v) => setVoiceInputMode(v as 'compose' | 'autosend' | 'handsfree')}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"compose\">Fill the message box (review, then Enter)</SelectItem>\n <SelectItem value=\"autosend\">Send immediately (speak-and-send)</SelectItem>\n </SelectContent>\n </Select>\n </Field>\n </section>\n )\n}\n\ninterface StewardConfig {\n enabled: boolean\n provider: ProviderName\n model?: string\n effort?: 'low' | 'medium' | 'high' | 'xhigh' | 'max'\n permissionMode: string\n keepaliveSeconds: number\n}\n\nconst EFFORTS = ['low', 'medium', 'high', 'xhigh', 'max'] as const\nconst DEFAULT_STEWARD: StewardConfig = { enabled: false, provider: 'claude', permissionMode: 'open', keepaliveSeconds: 300 }\n\n// Global, provider-independent steward config (issue #167). Stewards are\n// auto-provisioned per repo from these settings to resolve conflicts / diverged\n// bases that can't auto-merge. External system: the /steward-config API.\nfunction StewardSettings() {\n const [config, setConfig] = useState<StewardConfig>(DEFAULT_STEWARD)\n const [status, setStatus] = useState('')\n\n useEffect(() => {\n api<{ value: StewardConfig }>('GET', '/steward-config')\n .then((entry) => setConfig({ ...DEFAULT_STEWARD, ...entry.value }))\n .catch((e) => setStatus((e as Error).message))\n }, [])\n\n const update = (patch: Partial<StewardConfig>) => setConfig((c) => ({ ...c, ...patch }))\n\n async function save() {\n try {\n const saved = await api<{ value: StewardConfig }>('PUT', '/steward-config', config)\n setConfig({ ...DEFAULT_STEWARD, ...saved.value })\n setStatus('Steward config saved')\n } catch (e) {\n setStatus((e as Error).message)\n }\n }\n\n return (\n <section className=\"space-y-3 rounded-lg border p-4\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n <GitMerge className=\"w-4 h-4\" />\n <div>\n <h2 className=\"text-sm font-semibold\">Stewards</h2>\n <p className=\"text-xs text-muted-foreground\">Auto-resolve merge conflicts & diverged branches across all repos. Provider-independent — applies to every repo's steward.</p>\n </div>\n </div>\n <Switch checked={config.enabled} onCheckedChange={(v) => update({ enabled: v })} />\n </div>\n\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <Field label=\"Provider\">\n <Select value={config.provider} onValueChange={(v) => update({ provider: v as ProviderName })}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n {providers.map((p) => <SelectItem key={p} value={p}>{p}</SelectItem>)}\n </SelectContent>\n </Select>\n </Field>\n <Field label=\"Model (optional)\">\n <Input value={config.model ?? ''} placeholder=\"e.g. gpt-5.5\" onChange={(e) => update({ model: e.target.value.trim() || undefined })} />\n </Field>\n <Field label=\"Effort\">\n <Select value={config.effort ?? 'default'} onValueChange={(v) => update({ effort: v === 'default' ? undefined : v as StewardConfig['effort'] })}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"default\">Provider default</SelectItem>\n {EFFORTS.map((e) => <SelectItem key={e} value={e}>{e}</SelectItem>)}\n </SelectContent>\n </Select>\n </Field>\n <Field label=\"Idle timeout (seconds)\">\n <Input type=\"number\" value={config.keepaliveSeconds} onChange={(e) => update({ keepaliveSeconds: Number(e.target.value) || 300 })} />\n </Field>\n </div>\n\n <div className=\"flex items-center gap-2 pt-1\">\n <Button onClick={save}><Save className=\"w-4 h-4\" />Save</Button>\n {status && <p className=\"text-sm text-muted-foreground\">{status}</p>}\n </div>\n </section>\n )\n}\n\nfunction Field({ label, children }: { label: string; children: React.ReactNode }) {\n return <label className=\"block space-y-1.5 text-sm\"><span className=\"text-muted-foreground\">{label}</span>{children}</label>\n}\n\nfunction lines(value: string): string[] {\n return value.split('\\n').map((line) => line.trim()).filter(Boolean)\n}\n\nfunction recordLines(value: Record<string, string>): string {\n return Object.entries(value).map(([key, item]) => `${key}=${item}`).join('\\n')\n}\n\nfunction parseRecordLines(value: string): Record<string, string> {\n return Object.fromEntries(lines(value).map((line) => {\n const idx = line.indexOf('=')\n return idx >= 0 ? [line.slice(0, idx).trim(), line.slice(idx + 1)] : [line, '']\n }))\n}\n"],"mappings":"obA4BM,EAA4B,CAAC,SAAU,QAAQ,CAErD,SAAgB,GAAe,CAC7B,GAAM,CAAC,EAAS,IAAA,EAAA,EAAA,UAAuD,EAAE,CAAC,CACpE,CAAC,EAAU,IAAA,EAAA,EAAA,UAAsC,SAAS,CAC1D,CAAC,EAAQ,IAAA,EAAA,EAAA,UAAsB,GAAG,EAExC,EAAA,EAAA,eAAgB,CACd,EAAoC,MAAO,oBAAoB,CAC5D,KAAK,EAAW,CAChB,MAAO,GAAM,EAAW,EAAY,QAAQ,CAAC,EAC/C,EAAE,CAAC,CAEN,IAAM,EAAS,EAAQ,GACjB,EAAU,GAAmC,CAC5C,GACL,EAAW,CAAE,GAAG,GAAU,GAAW,CAAE,GAAG,EAAQ,GAAG,EAAO,CAAE,CAAC,EAGjE,eAAe,GAAO,CACpB,GAAI,CAAC,EAAQ,OACb,IAAM,EAAQ,MAAM,EAAoB,MAAO,cAAc,EAAS,SAAU,EAAO,CACvF,EAAW,CAAE,GAAG,GAAU,GAAW,EAAO,CAAC,CAC7C,EAAU,GAAG,EAAS,QAAQ,CAGhC,eAAe,GAAO,CACpB,IAAM,EAAS,MAAM,EAAoD,OAAQ,cAAc,EAAS,cAAc,CACtH,EAAU,EAAO,GAAK,GAAG,EAAS,YAAY,EAAO,MAAQ,UAAY,EAAO,OAAS,oBAAoB,CAG/G,OACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,qBAAf,EACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,mDAAf,EACE,EAAA,EAAA,MAAC,MAAD,CAAA,SAAA,EACE,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,iCAAwB,WAAa,CAAA,EACnD,EAAA,EAAA,KAAC,IAAD,CAAG,UAAU,yCAAgC,gCAAiC,CAAA,CAC1E,CAAA,CAAA,EACN,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,sBACZ,EAAU,IAAK,IACd,EAAA,EAAA,MAAC,EAAD,CAAuB,QAAS,IAAa,EAAW,UAAY,UAAW,YAAe,EAAY,EAAS,UAAnH,EACE,EAAA,EAAA,KAAC,EAAD,CAAU,UAAU,UAAY,CAAA,CAAC,EAC1B,EAFI,EAEJ,CACT,CACE,CAAA,CACF,GAEL,IACC,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,uEAAf,EACE,EAAA,EAAA,MAAC,UAAD,CAAS,UAAU,qBAAnB,EACE,EAAA,EAAA,KAAC,EAAD,CAAO,MAAM,oBACX,EAAA,EAAA,KAAC,EAAD,CAAO,MAAO,EAAO,QAAS,SAAW,GAAM,EAAO,CAAE,QAAS,EAAE,OAAO,MAAO,CAAC,CAAI,CAAA,CAChF,CAAA,EACR,EAAA,EAAA,KAAC,EAAD,CAAO,MAAM,8BACX,EAAA,EAAA,KAAC,EAAD,CAAU,KAAM,EAAG,MAAO,EAAO,YAAY,KAAK;EAAK,CAAE,SAAW,GAAM,EAAO,CAAE,YAAa,EAAM,EAAE,OAAO,MAAM,CAAE,CAAC,CAAI,CAAA,CACtH,CAAA,EACR,EAAA,EAAA,KAAC,EAAD,CAAO,MAAM,+BACX,EAAA,EAAA,KAAC,EAAD,CAAU,KAAM,EAAG,MAAO,EAAO,WAAW,KAAK;EAAK,CAAE,SAAW,GAAM,EAAO,CAAE,WAAY,EAAM,EAAE,OAAO,MAAM,CAAE,CAAC,CAAI,CAAA,CACpH,CAAA,EACR,EAAA,EAAA,KAAC,EAAD,CAAO,MAAM,wBACX,EAAA,EAAA,KAAC,EAAD,CAAU,KAAM,EAAG,MAAO,EAAY,EAAO,IAAI,CAAE,SAAW,GAAM,EAAO,CAAE,IAAK,EAAiB,EAAE,OAAO,MAAM,CAAE,CAAC,CAAI,CAAA,CACnH,CAAA,CACA,IAEV,EAAA,EAAA,MAAC,UAAD,CAAS,UAAU,qBAAnB,EACE,EAAA,EAAA,KAAC,EAAD,CAAO,MAAM,yBACX,EAAA,EAAA,KAAC,EAAD,CAAU,KAAM,EAAG,MAAO,EAAO,oBAAoB,KAAK;EAAK,CAAE,SAAW,GAAM,EAAO,CAAE,oBAAqB,EAAM,EAAE,OAAO,MAAM,CAAE,CAAC,CAAI,CAAA,CACtI,CAAA,EACR,EAAA,EAAA,KAAC,EAAD,CAAO,MAAM,iBACX,EAAA,EAAA,KAAC,EAAD,CAAU,KAAM,EAAG,MAAO,EAAO,YAAY,KAAK;EAAK,CAAE,SAAW,GAAM,EAAO,CAAE,YAAa,EAAM,EAAE,OAAO,MAAM,CAAE,CAAC,CAAI,CAAA,CACtH,CAAA,EACR,EAAA,EAAA,KAAC,EAAD,CAAO,MAAM,0BACX,EAAA,EAAA,KAAC,EAAD,CAAO,MAAO,EAAO,oBAAqB,SAAW,GAAM,EAAO,CAAE,oBAAqB,EAAE,OAAO,MAAO,CAAC,CAAI,CAAA,CACxG,CAAA,EACR,EAAA,EAAA,KAAC,EAAD,CAAO,MAAM,8BACX,EAAA,EAAA,MAAC,EAAD,CAAQ,MAAO,EAAO,iBAAmB,QAAS,cAAgB,GAAM,EAAO,CAAE,gBAAiB,EAAuB,CAAC,UAA1H,EACE,EAAA,EAAA,KAAC,EAAD,CAAA,UAAe,EAAA,EAAA,KAAC,EAAD,EAAe,CAAA,CAAgB,CAAA,EAC9C,EAAA,EAAA,MAAC,EAAD,CAAA,SAAA,EACE,EAAA,EAAA,KAAC,EAAD,CAAY,MAAM,iBAAQ,sBAAgC,CAAA,EAC1D,EAAA,EAAA,KAAC,EAAD,CAAY,MAAM,gBAAO,oCAA8C,CAAA,CACzD,CAAA,CAAA,CACT,GACH,CAAA,EACR,EAAA,EAAA,KAAC,EAAD,CAAO,MAAM,wBACX,EAAA,EAAA,KAAC,EAAD,CAAO,MAAO,EAAO,SAAS,WAAY,SAAW,GAAM,EAAO,CAAE,SAAU,CAAE,GAAG,EAAO,SAAU,WAAY,EAAE,OAAO,MAAO,CAAE,CAAC,CAAI,CAAA,CACjI,CAAA,EACR,EAAA,EAAA,KAAC,EAAD,CAAO,MAAM,6BACX,EAAA,EAAA,KAAC,EAAD,CAAO,KAAK,SAAS,MAAO,EAAO,SAAS,kBAAmB,SAAW,GAAM,EAAO,CAAE,SAAU,CAAE,GAAG,EAAO,SAAU,kBAAmB,OAAO,EAAE,OAAO,MAAM,EAAI,IAAO,CAAE,CAAC,CAAI,CAAA,CAC9K,CAAA,EACR,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,2BAAf,EACE,EAAA,EAAA,MAAC,EAAD,CAAQ,QAAS,WAAjB,EAAuB,EAAA,EAAA,KAAC,EAAD,CAAM,UAAU,UAAY,CAAA,CAAA,OAAa,IAChE,EAAA,EAAA,MAAC,EAAD,CAAQ,QAAQ,UAAU,QAAS,WAAnC,EAAyC,EAAA,EAAA,KAAC,EAAD,CAAW,UAAU,UAAY,CAAA,CAAA,OAAa,GACnF,GACL,IAAU,EAAA,EAAA,KAAC,IAAD,CAAG,UAAU,yCAAiC,EAAW,CAAA,CAC5D,GACN,IAGR,EAAA,EAAA,KAAC,EAAD,EAAuB,CAAA,EAEvB,EAAA,EAAA,KAAC,EAAD,EAAqB,CAAA,EAErB,EAAA,EAAA,KAAC,EAAD,EAAmB,CAAA,EAEnB,EAAA,EAAA,KAAC,EAAD,EAAmB,CAAA,EAEnB,EAAA,EAAA,KAAC,EAAD,EAAiB,CAAA,CACb,GAQV,IAAM,EAAqC,CAAE,aAAc,EAAE,CAAE,CAK/D,SAAS,GAAoB,CAC3B,GAAM,CAAC,EAAQ,IAAA,EAAA,EAAA,UAAuC,EAAkB,CAClE,CAAC,EAAQ,IAAA,EAAA,EAAA,UAAsB,GAAG,EAExC,EAAA,EAAA,eAAgB,CACd,EAAgC,MAAO,oBAAoB,CACxD,KAAM,GAAU,EAAU,CAAE,GAAG,EAAmB,GAAG,EAAM,MAAO,CAAC,CAAC,CACpE,MAAO,GAAM,EAAW,EAAY,QAAQ,CAAC,EAC/C,EAAE,CAAC,CAEN,eAAe,GAAO,CACpB,GAAI,CACF,IAAM,EAAQ,MAAM,EAAgC,MAAO,oBAAqB,EAAO,CACvF,EAAU,CAAE,GAAG,EAAmB,GAAG,EAAM,MAAO,CAAC,CACnD,EAAU,yBAAyB,OAC5B,EAAG,CACV,EAAW,EAAY,QAAQ,EAInC,OACE,EAAA,EAAA,MAAC,UAAD,CAAS,UAAU,2CAAnB,EACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,mCAAf,EACE,EAAA,EAAA,KAAC,EAAD,CAAe,UAAU,UAAY,CAAA,EACrC,EAAA,EAAA,MAAC,MAAD,CAAA,SAAA,EACE,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,iCAAwB,6BAA+B,CAAA,EACrE,EAAA,EAAA,MAAC,IAAD,CAAG,UAAU,yCAAb,CAA6C,wJACmH,EAAA,EAAA,KAAC,OAAD,CAAA,SAAM,YAAgB,CAAA,SAAI,EAAA,EAAA,KAAC,OAAD,CAAA,SAAM,cAAkB,CAAA,gDAA2C,EAAA,EAAA,MAAC,OAAD,CAAA,SAAA,CAAM,OAAK,KAAY,CAAA,CAAA,uEAChR,GACA,CAAA,CAAA,CACF,IACN,EAAA,EAAA,KAAC,EAAD,CAAO,MAAM,6BACX,EAAA,EAAA,KAAC,EAAD,CACE,KAAM,EACN,YAAa;aACb,MAAO,EAAO,aAAa,KAAK;EAAK,CACrC,SAAW,GAAM,EAAU,CAAE,GAAG,EAAQ,aAAc,EAAM,EAAE,OAAO,MAAM,CAAE,CAAC,CAC9E,CAAA,CACI,CAAA,EACR,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,wCAAf,EACE,EAAA,EAAA,MAAC,EAAD,CAAQ,QAAS,WAAjB,EAAuB,EAAA,EAAA,KAAC,EAAD,CAAM,UAAU,UAAY,CAAA,CAAA,OAAa,GAC/D,IAAU,EAAA,EAAA,KAAC,IAAD,CAAG,UAAU,yCAAiC,EAAW,CAAA,CAChE,GACE,GAcd,IAAM,EAAiC,CAAE,SAAU,SAAU,CAE7D,SAAS,GAAkB,CACzB,GAAM,CAAC,EAAQ,IAAA,EAAA,EAAA,UAAqC,EAAgB,CAC9D,CAAC,EAAQ,IAAA,EAAA,EAAA,UAAsB,GAAG,EAExC,EAAA,EAAA,eAAgB,CACd,EAAgC,MAAO,0BAA0B,CAC9D,KAAM,GAAU,EAAU,CAAE,GAAG,EAAiB,GAAG,EAAM,MAAO,CAAC,CAAC,CAClE,MAAO,GAAM,CACZ,GAAK,EAA0B,SAAW,IAAK,CAC7C,EAAU,EAAgB,CAC1B,OAEF,EAAW,EAAY,QAAQ,EAC/B,EACH,EAAE,CAAC,CAEN,eAAe,GAAO,CACpB,GAAI,CACF,IAAM,EAAQ,MAAM,EAAgC,MAAO,0BAA2B,CAAE,MAAO,EAAQ,UAAW,YAAa,CAAC,CAChI,EAAU,CAAE,GAAG,EAAiB,GAAG,EAAM,MAAO,CAAC,CACjD,EAAU,uBAAuB,OAC1B,EAAG,CACV,EAAW,EAAY,QAAQ,EAInC,OACE,EAAA,EAAA,MAAC,UAAD,CAAS,UAAU,2CAAnB,EACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,mCAAf,EACE,EAAA,EAAA,KAAC,EAAD,CAAgB,UAAU,UAAY,CAAA,EACtC,EAAA,EAAA,MAAC,MAAD,CAAA,SAAA,EACE,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,iCAAwB,iBAAmB,CAAA,EACzD,EAAA,EAAA,KAAC,IAAD,CAAG,UAAU,yCAAgC,sJAAuJ,CAAA,CAChM,CAAA,CAAA,CACF,IAEN,EAAA,EAAA,KAAC,EAAD,CAAO,MAAM,oCACX,EAAA,EAAA,MAAC,EAAD,CAAQ,MAAO,EAAO,SAAU,cAAgB,GAAM,EAAU,CAAE,SAAU,EAAsB,CAAC,UAAnG,EACE,EAAA,EAAA,KAAC,EAAD,CAAA,UAAe,EAAA,EAAA,KAAC,EAAD,EAAe,CAAA,CAAgB,CAAA,EAC9C,EAAA,EAAA,MAAC,EAAD,CAAA,SAAA,EACE,EAAA,EAAA,KAAC,EAAD,CAAY,MAAM,kBAAS,SAAmB,CAAA,EAC9C,EAAA,EAAA,KAAC,EAAD,CAAY,MAAM,cAAK,eAAyB,CAAA,CAClC,CAAA,CAAA,CACT,GACH,CAAA,EAER,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,wCAAf,EACE,EAAA,EAAA,MAAC,EAAD,CAAQ,QAAS,WAAjB,EAAuB,EAAA,EAAA,KAAC,EAAD,CAAM,UAAU,UAAY,CAAA,CAAA,OAAa,GAC/D,IAAU,EAAA,EAAA,KAAC,IAAD,CAAG,UAAU,yCAAiC,EAAW,CAAA,CAChE,GACE,GASd,SAAS,GAAsB,CAC7B,IAAM,EAAgB,EAAe,GAAM,EAAE,cAAc,CACrD,EAAM,EAAe,GAAM,EAAE,IAAI,CACvC,OACE,EAAA,EAAA,KAAC,UAAD,CAAS,UAAU,4CACjB,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,mDAAf,EACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,mCAAf,EACE,EAAA,EAAA,KAAC,EAAD,CAAO,UAAU,UAAY,CAAA,EAC7B,EAAA,EAAA,MAAC,MAAD,CAAA,SAAA,EACE,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,iCAAwB,yBAA2B,CAAA,EACjE,EAAA,EAAA,KAAC,IAAD,CAAG,UAAU,yCAAgC,oJAA0J,CAAA,CACnM,CAAA,CAAA,CACF,IACN,EAAA,EAAA,KAAC,EAAD,CAAQ,QAAS,EAAe,gBAAkB,GAAM,EAAI,CAAE,cAAe,EAAG,CAAC,CAAI,CAAA,CACjF,GACE,CAAA,CAQd,SAAS,GAAgB,CACvB,IAAM,EAAkB,EAAe,GAAM,EAAE,gBAAgB,CACzD,EAAqB,EAAe,GAAM,EAAE,mBAAmB,CAC/D,EAAe,EAAe,GAAM,EAAE,aAAa,CACnD,EAAkB,EAAe,GAAM,EAAE,gBAAgB,CACzD,EAAsB,EAAe,GAAM,EAAE,oBAAoB,CACjE,EAAyB,EAAe,GAAM,EAAE,uBAAuB,CACvE,EAAuB,EAAe,GAAM,EAAE,qBAAqB,CACnE,EAA0B,EAAe,GAAM,EAAE,wBAAwB,CACzE,EAAiB,EAAe,GAAM,EAAE,eAAe,CACvD,EAAoB,EAAe,GAAM,EAAE,kBAAkB,CAI7D,CAAC,EAAe,IAAA,EAAA,EAAA,cAAmC,GAAuB,CAAC,EACjF,EAAA,EAAA,eAAgB,CACd,GAAI,OAAO,OAAW,KAAe,EAAE,oBAAqB,QAAS,OACrE,IAAM,MAAgB,EAAiB,GAAuB,CAAC,CAG/D,OAFA,GAAS,CACT,OAAO,gBAAgB,mBAAmB,gBAAiB,EAAQ,KACtD,OAAO,gBAAgB,sBAAsB,gBAAiB,EAAQ,EAClF,EAAE,CAAC,CAEN,IAAM,EAAgB,EAAc,KAAM,GAAM,EAAE,KAAO,EAAoB,CACzE,EACA,CAAC,GAAG,EAAe,CAAE,GAAI,EAAqB,MAAO,EAAqB,CAAC,CAE/E,OACE,EAAA,EAAA,MAAC,UAAD,CAAS,UAAU,2CAAnB,EACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,mDAAf,EACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,mCAAf,EACE,EAAA,EAAA,KAAC,EAAD,CAAS,UAAU,UAAY,CAAA,EAC/B,EAAA,EAAA,MAAC,MAAD,CAAA,SAAA,EACE,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,iCAAwB,QAAU,CAAA,EAChD,EAAA,EAAA,KAAC,IAAD,CAAG,UAAU,yCAAgC,gFAAiF,CAAA,CAC1H,CAAA,CAAA,CACF,IACN,EAAA,EAAA,KAAC,EAAD,CAAQ,QAAS,EAAiB,gBAAiB,EAAsB,CAAA,CACrE,IACN,EAAA,EAAA,KAAC,EAAD,CAAO,MAAM,0BACX,EAAA,EAAA,MAAC,EAAD,CAAQ,MAAO,EAAc,cAAgB,GAAM,EAAgB,EAA0B,UAA7F,EACE,EAAA,EAAA,KAAC,EAAD,CAAA,UAAe,EAAA,EAAA,KAAC,EAAD,EAAe,CAAA,CAAgB,CAAA,EAC9C,EAAA,EAAA,MAAC,EAAD,CAAA,SAAA,EACE,EAAA,EAAA,KAAC,EAAD,CAAY,MAAM,kBAAS,mDAA6D,CAAA,EACxF,EAAA,EAAA,KAAC,EAAD,CAAY,MAAM,mBAAU,2BAAqC,CAAA,CACnD,CAAA,CAAA,CACT,GACH,CAAA,EACR,EAAA,EAAA,KAAC,EAAD,CAAO,MAAM,yBACX,EAAA,EAAA,MAAC,EAAD,CAAQ,MAAO,EAAqB,cAAe,WAAnD,EACE,EAAA,EAAA,KAAC,EAAD,CAAA,UAAe,EAAA,EAAA,KAAC,EAAD,EAAe,CAAA,CAAgB,CAAA,EAC9C,EAAA,EAAA,KAAC,EAAD,CAAA,SACG,EAAc,IAAK,IAAM,EAAA,EAAA,KAAC,EAAD,CAAuB,MAAO,EAAE,YAAK,EAAE,MAAmB,CAAzC,EAAE,GAAuC,CAAC,CACvE,CAAA,CACT,GACH,CAAA,EACR,EAAA,EAAA,KAAC,EAAD,CAAO,MAAM,0BACX,EAAA,EAAA,MAAC,EAAD,CAAQ,MAAO,GAAwB,cAAe,cAAgB,GAAM,EAAwB,IAAM,cAAgB,GAAK,EAAE,UAAjI,EACE,EAAA,EAAA,KAAC,EAAD,CAAA,UAAe,EAAA,EAAA,KAAC,EAAD,EAAe,CAAA,CAAgB,CAAA,EAC9C,EAAA,EAAA,MAAC,EAAD,CAAA,SAAA,EACE,EAAA,EAAA,KAAC,EAAD,CAAY,MAAM,uBAAc,iBAA2B,CAAA,CAC1D,EAAc,IAAK,IAAM,EAAA,EAAA,KAAC,EAAD,CAAwB,MAAO,EAAE,aAAM,EAAE,MAAmB,CAA3C,EAAE,IAAyC,CAAC,CACzE,CAAA,CAAA,CACT,GACH,CAAA,EACR,EAAA,EAAA,KAAC,EAAD,CAAO,MAAM,+BACX,EAAA,EAAA,MAAC,EAAD,CAAQ,MAAO,EAAgB,cAAgB,GAAM,EAAkB,EAA0C,UAAjH,EACE,EAAA,EAAA,KAAC,EAAD,CAAA,UAAe,EAAA,EAAA,KAAC,EAAD,EAAe,CAAA,CAAgB,CAAA,EAC9C,EAAA,EAAA,MAAC,EAAD,CAAA,SAAA,EACE,EAAA,EAAA,KAAC,EAAD,CAAY,MAAM,mBAAU,4CAAsD,CAAA,EAClF,EAAA,EAAA,KAAC,EAAD,CAAY,MAAM,oBAAW,oCAA8C,CAAA,CAC7D,CAAA,CAAA,CACT,GACH,CAAA,CACA,GAad,IAAM,EAAU,CAAC,MAAO,SAAU,OAAQ,QAAS,MAAM,CACnD,EAAiC,CAAE,QAAS,GAAO,SAAU,SAAU,eAAgB,OAAQ,iBAAkB,IAAK,CAK5H,SAAS,GAAkB,CACzB,GAAM,CAAC,EAAQ,IAAA,EAAA,EAAA,UAAqC,EAAgB,CAC9D,CAAC,EAAQ,IAAA,EAAA,EAAA,UAAsB,GAAG,EAExC,EAAA,EAAA,eAAgB,CACd,EAA8B,MAAO,kBAAkB,CACpD,KAAM,GAAU,EAAU,CAAE,GAAG,EAAiB,GAAG,EAAM,MAAO,CAAC,CAAC,CAClE,MAAO,GAAM,EAAW,EAAY,QAAQ,CAAC,EAC/C,EAAE,CAAC,CAEN,IAAM,EAAU,GAAkC,EAAW,IAAO,CAAE,GAAG,EAAG,GAAG,EAAO,EAAE,CAExF,eAAe,GAAO,CACpB,GAAI,CACF,IAAM,EAAQ,MAAM,EAA8B,MAAO,kBAAmB,EAAO,CACnF,EAAU,CAAE,GAAG,EAAiB,GAAG,EAAM,MAAO,CAAC,CACjD,EAAU,uBAAuB,OAC1B,EAAG,CACV,EAAW,EAAY,QAAQ,EAInC,OACE,EAAA,EAAA,MAAC,UAAD,CAAS,UAAU,2CAAnB,EACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,6CAAf,EACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,mCAAf,EACE,EAAA,EAAA,KAAC,EAAD,CAAU,UAAU,UAAY,CAAA,EAChC,EAAA,EAAA,MAAC,MAAD,CAAA,SAAA,EACE,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,iCAAwB,WAAa,CAAA,EACnD,EAAA,EAAA,KAAC,IAAD,CAAG,UAAU,yCAAgC,6HAAuI,CAAA,CAChL,CAAA,CAAA,CACF,IACN,EAAA,EAAA,KAAC,EAAD,CAAQ,QAAS,EAAO,QAAS,gBAAkB,GAAM,EAAO,CAAE,QAAS,EAAG,CAAC,CAAI,CAAA,CAC/E,IAEN,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,qCAAf,EACE,EAAA,EAAA,KAAC,EAAD,CAAO,MAAM,qBACX,EAAA,EAAA,MAAC,EAAD,CAAQ,MAAO,EAAO,SAAU,cAAgB,GAAM,EAAO,CAAE,SAAU,EAAmB,CAAC,UAA7F,EACE,EAAA,EAAA,KAAC,EAAD,CAAA,UAAe,EAAA,EAAA,KAAC,EAAD,EAAe,CAAA,CAAgB,CAAA,EAC9C,EAAA,EAAA,KAAC,EAAD,CAAA,SACG,EAAU,IAAK,IAAM,EAAA,EAAA,KAAC,EAAD,CAAoB,MAAO,WAAI,EAAe,CAA7B,EAA6B,CAAC,CACvD,CAAA,CACT,GACH,CAAA,EACR,EAAA,EAAA,KAAC,EAAD,CAAO,MAAM,6BACX,EAAA,EAAA,KAAC,EAAD,CAAO,MAAO,EAAO,OAAS,GAAI,YAAY,eAAe,SAAW,GAAM,EAAO,CAAE,MAAO,EAAE,OAAO,MAAM,MAAM,EAAI,IAAA,GAAW,CAAC,CAAI,CAAA,CACjI,CAAA,EACR,EAAA,EAAA,KAAC,EAAD,CAAO,MAAM,mBACX,EAAA,EAAA,MAAC,EAAD,CAAQ,MAAO,EAAO,QAAU,UAAW,cAAgB,GAAM,EAAO,CAAE,OAAQ,IAAM,UAAY,IAAA,GAAY,EAA8B,CAAC,UAA/I,EACE,EAAA,EAAA,KAAC,EAAD,CAAA,UAAe,EAAA,EAAA,KAAC,EAAD,EAAe,CAAA,CAAgB,CAAA,EAC9C,EAAA,EAAA,MAAC,EAAD,CAAA,SAAA,EACE,EAAA,EAAA,KAAC,EAAD,CAAY,MAAM,mBAAU,mBAA6B,CAAA,CACxD,EAAQ,IAAK,IAAM,EAAA,EAAA,KAAC,EAAD,CAAoB,MAAO,WAAI,EAAe,CAA7B,EAA6B,CAAC,CACrD,CAAA,CAAA,CACT,GACH,CAAA,EACR,EAAA,EAAA,KAAC,EAAD,CAAO,MAAM,mCACX,EAAA,EAAA,KAAC,EAAD,CAAO,KAAK,SAAS,MAAO,EAAO,iBAAkB,SAAW,GAAM,EAAO,CAAE,iBAAkB,OAAO,EAAE,OAAO,MAAM,EAAI,IAAK,CAAC,CAAI,CAAA,CAC/H,CAAA,CACJ,IAEN,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,wCAAf,EACE,EAAA,EAAA,MAAC,EAAD,CAAQ,QAAS,WAAjB,EAAuB,EAAA,EAAA,KAAC,EAAD,CAAM,UAAU,UAAY,CAAA,CAAA,OAAa,GAC/D,IAAU,EAAA,EAAA,KAAC,IAAD,CAAG,UAAU,yCAAiC,EAAW,CAAA,CAChE,GACE,GAId,SAAS,EAAM,CAAE,QAAO,YAA0D,CAChF,OAAO,EAAA,EAAA,MAAC,QAAD,CAAO,UAAU,qCAAjB,EAA6C,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,iCAAyB,EAAa,CAAA,CAAC,EAAiB,GAG9H,SAAS,EAAM,EAAyB,CACtC,OAAO,EAAM,MAAM;EAAK,CAAC,IAAK,GAAS,EAAK,MAAM,CAAC,CAAC,OAAO,QAAQ,CAGrE,SAAS,EAAY,EAAuC,CAC1D,OAAO,OAAO,QAAQ,EAAM,CAAC,KAAK,CAAC,EAAK,KAAU,GAAG,EAAI,GAAG,IAAO,CAAC,KAAK;EAAK,CAGhF,SAAS,EAAiB,EAAuC,CAC/D,OAAO,OAAO,YAAY,EAAM,EAAM,CAAC,IAAK,GAAS,CACnD,IAAM,EAAM,EAAK,QAAQ,IAAI,CAC7B,OAAO,GAAO,EAAI,CAAC,EAAK,MAAM,EAAG,EAAI,CAAC,MAAM,CAAE,EAAK,MAAM,EAAM,EAAE,CAAC,CAAG,CAAC,EAAM,GAAG,EAC/E,CAAC"}
|
|
1
|
+
{"version":3,"file":"settings-E4QJiNjt.js","names":[],"sources":["../../dashboard/src/components/views/settings.tsx"],"sourcesContent":["import { useEffect, useState } from 'react'\nimport { api } from '@/lib/api'\nimport { useRelayStore } from '@/store'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport { Textarea } from '@/components/ui/textarea'\nimport { Switch } from '@/components/ui/switch'\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'\nimport { KOKORO_VOICES, availableSpeechVoices } from '@/lib/voice'\nimport { Brain, FolderSymlink, GitMerge, GitPullRequest, Save, Terminal, TestTube2, Volume2 } from 'lucide-react'\n\ntype ProviderName = 'claude' | 'codex'\n\ninterface ProviderConfig {\n command: string\n defaultArgs: string[]\n env: Record<string, string>\n pluginDirs: string[]\n defaultCapabilities: string[]\n defaultApprovalMode: string\n defaultTags: string[]\n chatCaptureMode: 'final' | 'full'\n headless: {\n tmuxPrefix: string\n shutdownTimeoutMs: number\n }\n}\n\nconst providers: ProviderName[] = ['claude', 'codex']\n\nexport function SettingsView() {\n const [configs, setConfigs] = useState<Record<string, ProviderConfig>>({})\n const [selected, setSelected] = useState<ProviderName>('claude')\n const [status, setStatus] = useState('')\n\n useEffect(() => {\n api<Record<string, ProviderConfig>>('GET', '/providers/config')\n .then(setConfigs)\n .catch((e) => setStatus((e as Error).message))\n }, [])\n\n const config = configs[selected]\n const update = (patch: Partial<ProviderConfig>) => {\n if (!config) return\n setConfigs({ ...configs, [selected]: { ...config, ...patch } })\n }\n\n async function save() {\n if (!config) return\n const saved = await api<ProviderConfig>('PUT', `/providers/${selected}/config`, config)\n setConfigs({ ...configs, [selected]: saved })\n setStatus(`${selected} saved`)\n }\n\n async function test() {\n const result = await api<{ ok: boolean; path?: string; error?: string }>('POST', `/providers/${selected}/config/test`)\n setStatus(result.ok ? `${selected} command: ${result.path || 'found'}` : result.error || 'command not found')\n }\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between gap-3\">\n <div>\n <h1 className=\"text-xl font-semibold\">Settings</h1>\n <p className=\"text-sm text-muted-foreground\">Provider runner configuration</p>\n </div>\n <div className=\"flex gap-2\">\n {providers.map((provider) => (\n <Button key={provider} variant={selected === provider ? 'default' : 'outline'} onClick={() => setSelected(provider)}>\n <Terminal className=\"w-4 h-4\" />{provider}\n </Button>\n ))}\n </div>\n </div>\n\n {config && (\n <div className=\"grid gap-4 lg:grid-cols-[minmax(0,1fr)_minmax(280px,360px)]\">\n <section className=\"space-y-3\">\n <Field label=\"Command\">\n <Input value={config.command} onChange={(e) => update({ command: e.target.value })} />\n </Field>\n <Field label=\"Default arguments\">\n <Textarea rows={3} value={config.defaultArgs.join('\\n')} onChange={(e) => update({ defaultArgs: lines(e.target.value) })} />\n </Field>\n <Field label=\"Plugin directories\">\n <Textarea rows={3} value={config.pluginDirs.join('\\n')} onChange={(e) => update({ pluginDirs: lines(e.target.value) })} />\n </Field>\n <Field label=\"Environment\">\n <Textarea rows={5} value={recordLines(config.env)} onChange={(e) => update({ env: parseRecordLines(e.target.value) })} />\n </Field>\n </section>\n\n <section className=\"space-y-3\">\n <Field label=\"Capabilities\">\n <Textarea rows={3} value={config.defaultCapabilities.join('\\n')} onChange={(e) => update({ defaultCapabilities: lines(e.target.value) })} />\n </Field>\n <Field label=\"Tags\">\n <Textarea rows={3} value={config.defaultTags.join('\\n')} onChange={(e) => update({ defaultTags: lines(e.target.value) })} />\n </Field>\n <Field label=\"Approval mode\">\n <Input value={config.defaultApprovalMode} onChange={(e) => update({ defaultApprovalMode: e.target.value })} />\n </Field>\n <Field label=\"Chat capture mode\">\n <Select value={config.chatCaptureMode ?? 'final'} onValueChange={(v) => update({ chatCaptureMode: v as 'final' | 'full' })}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"final\">Final response only</SelectItem>\n <SelectItem value=\"full\">Full turn (intermediate messages)</SelectItem>\n </SelectContent>\n </Select>\n </Field>\n <Field label=\"tmux prefix\">\n <Input value={config.headless.tmuxPrefix} onChange={(e) => update({ headless: { ...config.headless, tmuxPrefix: e.target.value } })} />\n </Field>\n <Field label=\"Shutdown timeout\">\n <Input type=\"number\" value={config.headless.shutdownTimeoutMs} onChange={(e) => update({ headless: { ...config.headless, shutdownTimeoutMs: Number(e.target.value) || 10000 } })} />\n </Field>\n <div className=\"flex gap-2 pt-2\">\n <Button onClick={save}><Save className=\"w-4 h-4\" />Save</Button>\n <Button variant=\"outline\" onClick={test}><TestTube2 className=\"w-4 h-4\" />Test</Button>\n </div>\n {status && <p className=\"text-sm text-muted-foreground\">{status}</p>}\n </section>\n </div>\n )}\n\n <ChatDisplaySettings />\n\n <WorkspaceSettings />\n\n <LandingSettings />\n\n <StewardSettings />\n\n <VoiceSettings />\n </div>\n )\n}\n\ninterface WorkspaceConfig {\n symlinkPaths: string[]\n}\n\nconst DEFAULT_WORKSPACE: WorkspaceConfig = { symlinkPaths: [] }\n\n// Global isolated-worktree provisioning (#159 follow-up). A fresh git worktree only has\n// git-tracked files; node_modules are symlinked automatically and these extra untracked\n// paths are too. Only links what actually exists in main — missing entries are ignored.\nfunction WorkspaceSettings() {\n const [config, setConfig] = useState<WorkspaceConfig>(DEFAULT_WORKSPACE)\n const [status, setStatus] = useState('')\n\n useEffect(() => {\n api<{ value: WorkspaceConfig }>('GET', '/workspace-config')\n .then((entry) => setConfig({ ...DEFAULT_WORKSPACE, ...entry.value }))\n .catch((e) => setStatus((e as Error).message))\n }, [])\n\n async function save() {\n try {\n const saved = await api<{ value: WorkspaceConfig }>('PUT', '/workspace-config', config)\n setConfig({ ...DEFAULT_WORKSPACE, ...saved.value })\n setStatus('Workspace config saved')\n } catch (e) {\n setStatus((e as Error).message)\n }\n }\n\n return (\n <section className=\"space-y-3 rounded-lg border p-4\">\n <div className=\"flex items-center gap-2\">\n <FolderSymlink className=\"w-4 h-4\" />\n <div>\n <h2 className=\"text-sm font-semibold\">Isolated worktree symlinks</h2>\n <p className=\"text-xs text-muted-foreground\">\n Untracked files or filename patterns symlinked from main into each isolated worktree (the "Workspace" spawn option), one per line. Plain names like <code>AGENTS.md</code> or <code>.claude-rig</code> match files and directories; entries with <code>*?[]{'{}'}</code> are expanded as globs. A path is only linked if it exists in main.\n </p>\n </div>\n </div>\n <Field label=\"Paths / patterns\">\n <Textarea\n rows={5}\n placeholder={'AGENTS.md\\n.claude-rig'}\n value={config.symlinkPaths.join('\\n')}\n onChange={(e) => setConfig({ ...config, symlinkPaths: lines(e.target.value) })}\n />\n </Field>\n <div className=\"flex items-center gap-2 pt-1\">\n <Button onClick={save}><Save className=\"w-4 h-4\" />Save</Button>\n {status && <p className=\"text-sm text-muted-foreground\">{status}</p>}\n </div>\n </section>\n )\n}\n\ntype LandingStrategy = 'direct' | 'pr'\n\ninterface LandingConfig {\n strategy: LandingStrategy\n}\n\ninterface ConfigEntry<T> {\n value: T\n}\n\nconst DEFAULT_LANDING: LandingConfig = { strategy: 'direct' }\n\nfunction LandingSettings() {\n const [config, setConfig] = useState<LandingConfig>(DEFAULT_LANDING)\n const [status, setStatus] = useState('')\n\n useEffect(() => {\n api<ConfigEntry<LandingConfig>>('GET', '/config/landing/default')\n .then((entry) => setConfig({ ...DEFAULT_LANDING, ...entry.value }))\n .catch((e) => {\n if ((e as { status?: number }).status === 404) {\n setConfig(DEFAULT_LANDING)\n return\n }\n setStatus((e as Error).message)\n })\n }, [])\n\n async function save() {\n try {\n const saved = await api<ConfigEntry<LandingConfig>>('PUT', '/config/landing/default', { value: config, updatedBy: 'dashboard' })\n setConfig({ ...DEFAULT_LANDING, ...saved.value })\n setStatus('Landing config saved')\n } catch (e) {\n setStatus((e as Error).message)\n }\n }\n\n return (\n <section className=\"space-y-3 rounded-lg border p-4\">\n <div className=\"flex items-center gap-2\">\n <GitPullRequest className=\"w-4 h-4\" />\n <div>\n <h2 className=\"text-sm font-semibold\">Branch landing</h2>\n <p className=\"text-xs text-muted-foreground\">Instance default for lands without an explicit strategy. PR opens a pull request and Relay auto-completes on green; direct merges straight to main.</p>\n </div>\n </div>\n\n <Field label=\"Branch landing strategy\">\n <Select value={config.strategy} onValueChange={(v) => setConfig({ strategy: v as LandingStrategy })}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"direct\">Direct</SelectItem>\n <SelectItem value=\"pr\">Pull request</SelectItem>\n </SelectContent>\n </Select>\n </Field>\n\n <div className=\"flex items-center gap-2 pt-1\">\n <Button onClick={save}><Save className=\"w-4 h-4\" />Save</Button>\n {status && <p className=\"text-sm text-muted-foreground\">{status}</p>}\n </div>\n </section>\n )\n}\n\n// Chat display: per-viewer rendering preferences for the Chat panel. These are\n// client-side (persisted in the browser), not provider config — toggling is instant\n// and retroactive. Reasoning steps are still captured by the runner; this only\n// controls whether they're shown. The agent's narration (the terminal's `●` lines)\n// is always shown.\nfunction ChatDisplaySettings() {\n const showReasoning = useRelayStore((s) => s.showReasoning)\n const set = useRelayStore((s) => s.set)\n return (\n <section className=\"space-y-3 rounded-lg border p-4\">\n <div className=\"flex items-center justify-between gap-2\">\n <div className=\"flex items-center gap-2\">\n <Brain className=\"w-4 h-4\" />\n <div>\n <h2 className=\"text-sm font-semibold\">Show reasoning details</h2>\n <p className=\"text-xs text-muted-foreground\">Show the agent's internal thinking inline in chat, alongside its narration and tool steps. Off by default — narration is always shown either way.</p>\n </div>\n </div>\n <Switch checked={showReasoning} onCheckedChange={(v) => set({ showReasoning: v })} />\n </div>\n </section>\n )\n}\n\n// Voice settings: TTS output (speak agent responses — engine + per-engine voice)\n// and the push-to-talk mic-input behaviour. TTS config used to live inline in the\n// chat header; it moved here to declutter the header (especially on mobile). The\n// header keeps only the speaker on/off toggle for quick muting.\nfunction VoiceSettings() {\n const voiceTtsEnabled = useRelayStore((s) => s.voiceTtsEnabled)\n const setVoiceTtsEnabled = useRelayStore((s) => s.setVoiceTtsEnabled)\n const voiceTtsMode = useRelayStore((s) => s.voiceTtsMode)\n const setVoiceTtsMode = useRelayStore((s) => s.setVoiceTtsMode)\n const voiceTtsKokoroVoice = useRelayStore((s) => s.voiceTtsKokoroVoice)\n const setVoiceTtsKokoroVoice = useRelayStore((s) => s.setVoiceTtsKokoroVoice)\n const voiceTtsBrowserVoice = useRelayStore((s) => s.voiceTtsBrowserVoice)\n const setVoiceTtsBrowserVoice = useRelayStore((s) => s.setVoiceTtsBrowserVoice)\n const voiceInputMode = useRelayStore((s) => s.voiceInputMode)\n const setVoiceInputMode = useRelayStore((s) => s.setVoiceInputMode)\n\n // External sync: the browser loads its speech voices asynchronously, so\n // re-read them when the engine signals the list changed.\n const [browserVoices, setBrowserVoices] = useState(() => availableSpeechVoices())\n useEffect(() => {\n if (typeof window === 'undefined' || !('speechSynthesis' in window)) return\n const refresh = () => setBrowserVoices(availableSpeechVoices())\n refresh()\n window.speechSynthesis.addEventListener?.('voiceschanged', refresh)\n return () => window.speechSynthesis.removeEventListener?.('voiceschanged', refresh)\n }, [])\n\n const kokoroOptions = KOKORO_VOICES.some((v) => v.id === voiceTtsKokoroVoice)\n ? KOKORO_VOICES\n : [...KOKORO_VOICES, { id: voiceTtsKokoroVoice, label: voiceTtsKokoroVoice }]\n\n return (\n <section className=\"space-y-3 rounded-lg border p-4\">\n <div className=\"flex items-center justify-between gap-2\">\n <div className=\"flex items-center gap-2\">\n <Volume2 className=\"w-4 h-4\" />\n <div>\n <h2 className=\"text-sm font-semibold\">Voice</h2>\n <p className=\"text-xs text-muted-foreground\">Speak agent responses aloud in the active chat, and how push-to-talk behaves.</p>\n </div>\n </div>\n <Switch checked={voiceTtsEnabled} onCheckedChange={setVoiceTtsEnabled} />\n </div>\n <Field label=\"Speech engine\">\n <Select value={voiceTtsMode} onValueChange={(v) => setVoiceTtsMode(v as 'kokoro' | 'browser')}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"kokoro\">Kokoro (server, natural — falls back to browser)</SelectItem>\n <SelectItem value=\"browser\">Browser (Web Speech API)</SelectItem>\n </SelectContent>\n </Select>\n </Field>\n <Field label=\"Kokoro voice\">\n <Select value={voiceTtsKokoroVoice} onValueChange={setVoiceTtsKokoroVoice}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n {kokoroOptions.map((v) => <SelectItem key={v.id} value={v.id}>{v.label}</SelectItem>)}\n </SelectContent>\n </Select>\n </Field>\n <Field label=\"Browser voice\">\n <Select value={voiceTtsBrowserVoice || '__default__'} onValueChange={(v) => setVoiceTtsBrowserVoice(v === '__default__' ? '' : v)}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"__default__\">System default</SelectItem>\n {browserVoices.map((v) => <SelectItem key={v.uri} value={v.uri}>{v.label}</SelectItem>)}\n </SelectContent>\n </Select>\n </Field>\n <Field label=\"Push-to-talk input\">\n <Select value={voiceInputMode} onValueChange={(v) => setVoiceInputMode(v as 'compose' | 'autosend' | 'handsfree')}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"compose\">Fill the message box (review, then Enter)</SelectItem>\n <SelectItem value=\"autosend\">Send immediately (speak-and-send)</SelectItem>\n </SelectContent>\n </Select>\n </Field>\n </section>\n )\n}\n\ninterface StewardConfig {\n enabled: boolean\n provider: ProviderName\n model?: string\n effort?: 'low' | 'medium' | 'high' | 'xhigh' | 'max'\n permissionMode: string\n keepaliveSeconds: number\n}\n\nconst EFFORTS = ['low', 'medium', 'high', 'xhigh', 'max'] as const\nconst DEFAULT_STEWARD: StewardConfig = { enabled: false, provider: 'claude', permissionMode: 'open', keepaliveSeconds: 300 }\n\n// Global, provider-independent steward config (issue #167). Stewards are\n// auto-provisioned per repo from these settings to resolve conflicts / diverged\n// bases that can't auto-merge. External system: the /steward-config API.\nfunction StewardSettings() {\n const [config, setConfig] = useState<StewardConfig>(DEFAULT_STEWARD)\n const [status, setStatus] = useState('')\n\n useEffect(() => {\n api<{ value: StewardConfig }>('GET', '/steward-config')\n .then((entry) => setConfig({ ...DEFAULT_STEWARD, ...entry.value }))\n .catch((e) => setStatus((e as Error).message))\n }, [])\n\n const update = (patch: Partial<StewardConfig>) => setConfig((c) => ({ ...c, ...patch }))\n\n async function save() {\n try {\n const saved = await api<{ value: StewardConfig }>('PUT', '/steward-config', config)\n setConfig({ ...DEFAULT_STEWARD, ...saved.value })\n setStatus('Steward config saved')\n } catch (e) {\n setStatus((e as Error).message)\n }\n }\n\n return (\n <section className=\"space-y-3 rounded-lg border p-4\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n <GitMerge className=\"w-4 h-4\" />\n <div>\n <h2 className=\"text-sm font-semibold\">Stewards</h2>\n <p className=\"text-xs text-muted-foreground\">Auto-resolve merge conflicts & diverged branches across all repos. Provider-independent — applies to every repo's steward.</p>\n </div>\n </div>\n <Switch checked={config.enabled} onCheckedChange={(v) => update({ enabled: v })} />\n </div>\n\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <Field label=\"Provider\">\n <Select value={config.provider} onValueChange={(v) => update({ provider: v as ProviderName })}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n {providers.map((p) => <SelectItem key={p} value={p}>{p}</SelectItem>)}\n </SelectContent>\n </Select>\n </Field>\n <Field label=\"Model (optional)\">\n <Input value={config.model ?? ''} placeholder=\"e.g. gpt-5.5\" onChange={(e) => update({ model: e.target.value.trim() || undefined })} />\n </Field>\n <Field label=\"Effort\">\n <Select value={config.effort ?? 'default'} onValueChange={(v) => update({ effort: v === 'default' ? undefined : v as StewardConfig['effort'] })}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"default\">Provider default</SelectItem>\n {EFFORTS.map((e) => <SelectItem key={e} value={e}>{e}</SelectItem>)}\n </SelectContent>\n </Select>\n </Field>\n <Field label=\"Idle timeout (seconds)\">\n <Input type=\"number\" value={config.keepaliveSeconds} onChange={(e) => update({ keepaliveSeconds: Number(e.target.value) || 300 })} />\n </Field>\n </div>\n\n <div className=\"flex items-center gap-2 pt-1\">\n <Button onClick={save}><Save className=\"w-4 h-4\" />Save</Button>\n {status && <p className=\"text-sm text-muted-foreground\">{status}</p>}\n </div>\n </section>\n )\n}\n\nfunction Field({ label, children }: { label: string; children: React.ReactNode }) {\n return <label className=\"block space-y-1.5 text-sm\"><span className=\"text-muted-foreground\">{label}</span>{children}</label>\n}\n\nfunction lines(value: string): string[] {\n return value.split('\\n').map((line) => line.trim()).filter(Boolean)\n}\n\nfunction recordLines(value: Record<string, string>): string {\n return Object.entries(value).map(([key, item]) => `${key}=${item}`).join('\\n')\n}\n\nfunction parseRecordLines(value: string): Record<string, string> {\n return Object.fromEntries(lines(value).map((line) => {\n const idx = line.indexOf('=')\n return idx >= 0 ? [line.slice(0, idx).trim(), line.slice(idx + 1)] : [line, '']\n }))\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{r as e}from"./chunk-CilyBKbf.js";import{Bn as t,Gn as n,Hn as r,In as i,Ln as a,Pn as o,Un as s,Wn as c}from"./lucide-react-C3j5Huiw.js";import{B as l,C as u,D as d,I as f,O as p,W as m,X as h,Y as g,Z as _,_ as v,at as y,b,d as ee,et as x,it as S,j as C,nt as w,ot as T,p as E,rt as D,tt as O,w as te}from"./display-
|
|
1
|
+
import{r as e}from"./chunk-CilyBKbf.js";import{Bn as t,Gn as n,Hn as r,In as i,Ln as a,Pn as o,Un as s,Wn as c}from"./lucide-react-C3j5Huiw.js";import{B as l,C as u,D as d,I as f,O as p,W as m,X as h,Y as g,Z as _,_ as v,at as y,b,d as ee,et as x,it as S,j as C,nt as w,ot as T,p as E,rt as D,tt as O,w as te}from"./display-CketawEF.js";var k=e(n(),1),ne=e=>{let t,n=new Set,r=(e,r)=>{let i=typeof e==`function`?e(t):e;if(!Object.is(i,t)){let e=t;t=r??(typeof i!=`object`||!i)?i:Object.assign({},t,i),n.forEach(n=>n(t,e))}},i=()=>t,a={setState:r,getState:i,getInitialState:()=>o,subscribe:e=>(n.add(e),()=>n.delete(e))},o=t=e(r,i,a);return a},re=(e=>e?ne(e):ne),ie=e=>e;function ae(e,t=ie){let n=k.useSyncExternalStore(e.subscribe,k.useCallback(()=>t(e.getState()),[e,t]),k.useCallback(()=>t(e.getInitialState()),[e,t]));return k.useDebugValue(n),n}var oe=e=>{let t=re(e),n=e=>ae(t,e);return Object.assign(n,t),n},se=(e=>e?oe(e):oe);function ce(e,t){let n;try{n=e()}catch{return}return{getItem:e=>{let r=e=>e===null?null:JSON.parse(e,t?.reviver),i=n.getItem(e)??null;return i instanceof Promise?i.then(r):r(i)},setItem:(e,r)=>n.setItem(e,JSON.stringify(r,t?.replacer)),removeItem:e=>n.removeItem(e)}}var le=e=>t=>{try{let n=e(t);return n instanceof Promise?n:{then(e){return le(e)(n)},catch(e){return this}}}catch(e){return{then(e){return this},catch(t){return le(t)(e)}}}},ue=(e,t)=>(n,r,i)=>{let a={storage:ce(()=>window.localStorage),partialize:e=>e,version:0,merge:(e,t)=>({...t,...e}),...t},o=!1,s=0,c=new Set,l=new Set,u=a.storage;if(!u)return e((...e)=>{console.warn(`[zustand persist middleware] Unable to update item '${a.name}', the given storage is currently unavailable.`),n(...e)},r,i);let d=()=>{let e=a.partialize({...r()});return u.setItem(a.name,{state:e,version:a.version})},f=i.setState;i.setState=(e,t)=>(f(e,t),d());let p=e((...e)=>(n(...e),d()),r,i);i.getInitialState=()=>p;let m,h=()=>{if(!u)return;let e=++s;o=!1,c.forEach(e=>e(r()??p));let t=a.onRehydrateStorage?.call(a,r()??p)||void 0;return le(u.getItem.bind(u))(a.name).then(e=>{if(e)if(typeof e.version==`number`&&e.version!==a.version){if(a.migrate){let t=a.migrate(e.state,e.version);return t instanceof Promise?t.then(e=>[!0,e]):[!0,t]}console.error(`State loaded from storage couldn't be migrated since no migrate function was provided`)}else return[!1,e.state];return[!1,void 0]}).then(t=>{if(e!==s)return;let[i,o]=t;if(m=a.merge(o,r()??p),n(m,!0),i)return d()}).then(()=>{e===s&&(t?.(r(),void 0),m=r(),o=!0,l.forEach(e=>e(m)))}).catch(n=>{e===s&&t?.(void 0,n)})};return i.persist={setOptions:e=>{a={...a,...e},e.storage&&(u=e.storage)},clearStorage:()=>{u?.removeItem(a.name)},getOptions:()=>a,rehydrate:()=>h(),hasHydrated:()=>o,onHydrate:e=>(c.add(e),()=>{c.delete(e)}),onFinishHydration:e=>(l.add(e),()=>{l.delete(e)})},a.skipHydration||h(),m||p};function de(e){if(!e)return``;let t=e.replace(/\r\n/g,`
|
|
2
2
|
`);return t=t.replace(/```[^\n]*\n([\s\S]*?)```/g,(e,t)=>{let n=t.replace(/\n+$/,``).split(`
|
|
3
3
|
`).length;return` code block, ${n} ${n===1?`line`:`lines`}. `}),t=t.replace(/```[^\n]*/g,` code block. `),t=he(t),t=t.replace(/^#{1,6}\s+/gm,``),t=t.replace(/^\s*[-*+]\s+/gm,`. `),t=t.replace(/^\s*\d+\.\s+/gm,`. `),t=t.replace(/`([^`]+)`/g,`$1`),t=t.replace(/\[([^\]]+)\]\([^)]+\)/g,`$1`),t=t.replace(/(\*\*|__|\*|_)(.*?)\1/g,`$2`),t=t.replace(/[ \t]+/g,` `),t=t.replace(/\n{2,}/g,`. `),t=t.replace(/\s*\.\s*\.\s*(\.\s*)+/g,`. `),t.trim()}function fe(e){return/\|/.test(e)&&e.trim().length>0}function pe(e){return/^\s*\|?\s*:?-{2,}:?\s*(\|\s*:?-{2,}:?\s*)+\|?\s*$/.test(e)}function me(e){return e.trim().replace(/^\||\|$/g,``).split(`|`).map(e=>e.trim()).filter(e=>e.length>0)}function he(e){let t=e.split(`
|
|
4
4
|
`),n=[],r=0;for(;r<t.length;){if(fe(t[r])&&r+1<t.length&&pe(t[r+1])){let e=me(t[r]),i=r+2,a=0;for(;i<t.length&&fe(t[i])&&!pe(t[i]);)a++,i++;let o=e.length?`with columns ${e.join(`, `)}`:``,s=`${a} ${a===1?`row`:`rows`}`;n.push(`table ${o?`${o}, `:``}${s}.`.replace(/\s+/g,` `).trim()),r=i;continue}n.push(t[r]),r++}return n.join(`
|
|
@@ -6,4 +6,4 @@ import{r as e}from"./chunk-CilyBKbf.js";import{Bn as t,Gn as n,Hn as r,In as i,L
|
|
|
6
6
|
`),D=14e3,O=`You are continuing work from a previous agent session (${w}). Below is the conversation history. Treat it as context for your work, not as your own actions.\n\n${E.length>D?`...
|
|
7
7
|
`+E.slice(E.length-D):E}`,te=r.filter(e=>typeof e.id==`number`&&e.id>0).map(e=>e.id);e({spawnOrchId:C.id,spawnProvider:c||H(C),spawnModel:u||U(c||H(C)),spawnEffort:p,spawnProfile:i.spawnProfile||`default-relay`,spawnCwd:v||C.baseDir||``,spawnLabel:S,spawnApproval:x,spawnWorkspaceMode:b,spawnPrompt:`Continue from this previous session.`,spawnSystemPromptAppend:O,spawnCount:1,pendingForkImport:{sourcePeerId:a.id,sourceAgentId:a.id,sourceThreadId:a.id,sourceAgentLabel:w,messageIds:te},orchestratorSpawnOpen:!0})},openOrchestratorInstall(){e({orchestratorInstallOpen:!0})},openOrchestratorSpawnFor(n){let r=t(),i=r.orchestrators.find(e=>e.id===n),a=H(i),o=U(a),s=r.spawnProvider===a&&r.spawnModel===o?r.spawnEffort:``,c=r.spawnCwd&&f(r.spawnCwd,i?.baseDir)?r.spawnCwd:i?.baseDir||``;e({spawnOrchId:n,spawnProvider:a,spawnModel:o,spawnEffort:s,spawnProfile:r.spawnProfile||`default-relay`,spawnCwd:c,spawnLabel:``,spawnWorkspaceMode:`inherit`,spawnPrompt:``,spawnSystemPromptAppend:``,spawnCount:1,pendingForkImport:null,orchestratorSpawnOpen:!0})},selectSpawnHistory(n,r){let i=t(),a=i.orchestrators.find(e=>e.id===n&&e.status===`online`);if(!a){t().showError(`Unavailable`,`That orchestrator is no longer online.`);return}if(n===i.spawnOrchId){e({spawnCwd:r});return}let o=i.spawnProvider&&a.providers.includes(i.spawnProvider)?i.spawnProvider:H(a),s=i.spawnProvider===o&&i.spawnModel?i.spawnModel:U(o);e({spawnOrchId:n,spawnProvider:o,spawnModel:s,spawnEffort:i.spawnProvider===o&&i.spawnModel===s?i.spawnEffort:``,spawnCwd:r})},async submitOrchestratorSpawn(){let n=t();if(n.isSpawning)return;if(!n.spawnOrchId){t().showError(`Validation`,`Select an orchestrator.`);return}let r=n.orchestrators.find(e=>e.id===n.spawnOrchId);if(!r){t().showError(`Validation`,`Selected orchestrator is not available.`);return}let i=n.spawnCwd.trim();if(!i){t().showError(`Validation`,`Select a working directory.`);return}if(!f(i,r.baseDir)){t().showError(`Validation`,`Working directory must be under ${r.baseDir}.`);return}let a=n.pendingForkImport,s=a?1:Math.max(1,Math.min(10,Math.round(n.spawnCount)||1));e({isSpawning:!0});try{for(let e=0;e<s;e++){let t={provider:n.spawnProvider,orchestratorId:n.spawnOrchId,approvalMode:n.spawnApproval,workspaceMode:n.spawnWorkspaceMode||`inherit`};n.spawnModel&&(t.model=n.spawnModel),n.spawnEffort&&(t.effort=n.spawnEffort),n.spawnProfile&&(t.profile=n.spawnProfile),t.cwd=i,n.spawnLabel&&(t.label=s>1?`${n.spawnLabel} ${e+1}`:n.spawnLabel),n.spawnPrompt&&(t.prompt=n.spawnPrompt),n.spawnSystemPromptAppend&&(t.systemPromptAppend=n.spawnSystemPromptAppend);let r=(await o(`POST`,`/agents/spawn`,t)).command?.params?.spawnRequestId;a&&r&&a.messageIds.length>0&&await o(`POST`,`/chat/history-imports`,{targetSpawnRequestId:r,sourcePeerId:a.sourcePeerId,sourceAgentId:a.sourceAgentId,sourceThreadId:a.sourceThreadId,sourceAgentLabel:a.sourceAgentLabel,importedBy:y,messageIds:a.messageIds})}e({orchestratorSpawnOpen:!1,pendingForkImport:null,isSpawning:!1,spawnCwdHistory:[{orchId:n.spawnOrchId,cwd:i},...n.spawnCwdHistory.filter(e=>!(e.orchId===n.spawnOrchId&&e.cwd===i))].slice(0,5)}),await Promise.all([t().fetchAgents(),t().fetchOrchestrators(),t().fetchActivityEvents(),t().fetchChatHistoryImports()])}catch(n){e({isSpawning:!1}),t().showError(`Spawn Failed`,n.message)}},orchestratorAction(e,n,r,i){let a=n===`restart`?`Restart`:`Shutdown`,s=r?`agent "${r}"`:`all agents`;t().openConfirm(`${a} Agent`,`${a} ${s} on orchestrator "${e}"?`,async()=>{try{await o(`POST`,`/orchestrators/`+encodeURIComponent(e)+`/actions`,{action:n,agentId:r,...i?{surface:{component:i}}:{}}),await Promise.all([t().fetchOrchestrators(),t().fetchActivityEvents()])}catch(e){t().showError(`${a} Failed`,e.message)}})},upgradeOrchestrator(e,n){let r=n?` to v${n}`:` to match the relay`;t().openConfirm(`Upgrade Orchestrator`,`Upgrade "${e}"${r}? It will install the new version and restart itself.`,async()=>{try{await o(`POST`,`/orchestrators/`+encodeURIComponent(e)+`/actions`,{action:`upgrade`,...n?{targetVersion:n}:{}}),await Promise.all([t().fetchOrchestrators(),t().fetchActivityEvents()])}catch(e){t().showError(`Upgrade Failed`,e.message)}})},deleteOrchestrator(e){t().openConfirm(`Remove Orchestrator`,`Remove orchestrator "${e}"?`,async()=>{try{await o(`DELETE`,`/orchestrators/`+encodeURIComponent(e)),await Promise.all([t().fetchOrchestrators(),t().fetchActivityEvents()])}catch(e){t().showError(`Delete Failed`,e.message)}})},async browseSpawnDirectory(n){let r=t().spawnOrchId;if(!r)return;let i=t().spawnDirBrowser;e({spawnDirBrowser:{...i,loading:!0,error:``}});try{let i=n?`?path=`+encodeURIComponent(n):``,a=await o(`GET`,`/orchestrators/`+encodeURIComponent(r)+`/directories`+i);e({spawnDirBrowser:{open:!0,loading:!1,path:a.path||``,parent:a.parent||``,baseDir:a.baseDir||``,entries:a.entries||[],error:``},spawnCwd:a.path||t().spawnCwd})}catch(n){e({spawnDirBrowser:{...t().spawnDirBrowser,loading:!1,error:n.message}})}},selectSpawnDirectory(n){e({spawnCwd:n||t().spawnDirBrowser.path,spawnDirBrowser:{...t().spawnDirBrowser,open:!1}})}}),_t=(e,t)=>({managedPolicies:[],policyModal:{open:!1,editing:``,name:``,description:``,orchestratorId:``,cwd:``,enabled:void 0,provider:`claude`,rig:``,model:U(`claude`),effort:``,profile:`default-relay`,providerArgs:``,prompt:``,tags:``,capabilities:``,label:``,mode:`always-on`,permissionMode:`guarded`,restartOnUpdate:!0,scheduledDailyRestart:!1,keepaliveSeconds:`300`,backoffSchedule:`5,15,60,300`,backoffResetAfterSeconds:`600`,channelId:``},policyDirBrowser:{open:!1,loading:!1,path:``,parent:``,baseDir:``,entries:[],error:``},agentProfiles:[],profileModal:{open:!1,mode:`create`,profile:{name:``,description:``,provider:`any`,base:`host`,instructions:{system:``,append:[],repoInstructions:`allow`,globalInstructions:`allow`},relay:{context:!0,skills:!0,plugins:!0,statusLine:!0,mcp:!0},skills:[],plugins:[],mcp:{mode:`host`},hooks:{mode:`host`},permissions:{filesystem:`host`},env:{},providerOptions:{}}},async fetchManagedPolicies(){try{e({managedPolicies:await o(`GET`,`/spawn-policies/health`)})}catch{}},async fetchAgentProfiles(){try{e({agentProfiles:(await o(`GET`,`/agent-profiles`)).map(e=>e.value)})}catch{}},openPolicyCreate(){let n=t().orchestrators.filter(e=>e.status===`online`);if(!n.length){t().showError(`No Orchestrators`,`No orchestrators are currently online.`);return}e({policyModal:{open:!0,editing:``,name:``,description:``,orchestratorId:n[0].id,cwd:``,enabled:void 0,provider:H(n[0]),rig:``,model:U(H(n[0])),effort:``,profile:`default-relay`,providerArgs:``,prompt:``,tags:``,capabilities:``,label:``,mode:`always-on`,permissionMode:`guarded`,restartOnUpdate:!0,scheduledDailyRestart:!1,keepaliveSeconds:`300`,backoffSchedule:`5,15,60,300`,backoffResetAfterSeconds:`600`,channelId:``},policyDirBrowser:{open:!1,loading:!1,path:``,parent:``,baseDir:``,entries:[],error:``}})},openPolicyEdit(t){e({policyModal:{open:!0,editing:t.name,name:t.name,enabled:t.enabled,description:t.description||``,orchestratorId:t.orchestratorId,cwd:t.cwd,provider:t.provider,rig:t.rig||``,model:t.model||U(t.provider),effort:t.effort||``,profile:t.profile||`default-relay`,providerArgs:(t.providerArgs||[]).join(` `),prompt:t.prompt||``,tags:(t.tags||[]).join(`, `),capabilities:(t.capabilities||[]).join(`, `),label:t.label||``,mode:t.mode,permissionMode:t.permissionMode,restartOnUpdate:t.restartOnUpdate,scheduledDailyRestart:t.scheduledDailyRestart,keepaliveSeconds:String(t.onDemand?.keepaliveSeconds??300),backoffSchedule:(t.backoff?.schedule||[5,15,60,300]).join(`, `),backoffResetAfterSeconds:String(t.backoff?.resetAfterSeconds??600),channelId:t.binding?.channelId||``},policyDirBrowser:{open:!1,loading:!1,path:``,parent:``,baseDir:``,entries:[],error:``}})},async submitPolicy(){let n=t().policyModal;if(!n.name.trim()){t().showError(`Validation`,`Policy name is required.`);return}if(!n.orchestratorId){t().showError(`Validation`,`Select an orchestrator.`);return}if(!n.cwd.trim()){t().showError(`Validation`,`Working directory is required.`);return}let r=e=>e.split(/[,\s]+/).map(e=>e.trim()).filter(Boolean),i={name:n.name.trim(),...n.description.trim()?{description:n.description.trim()}:{},...n.enabled===void 0?{}:{enabled:n.enabled},orchestratorId:n.orchestratorId,cwd:n.cwd.trim(),provider:n.provider,...n.rig.trim()?{rig:n.rig.trim()}:{},...n.model?{model:n.model}:{},...n.effort?{effort:n.effort}:{},...n.profile?{profile:n.profile}:{},providerArgs:n.providerArgs.trim()?n.providerArgs.trim().split(/\s+/):[],...n.prompt.trim()?{prompt:n.prompt.trim()}:{},tags:r(n.tags),capabilities:r(n.capabilities),...n.label.trim()?{label:n.label.trim()}:{},mode:n.mode,permissionMode:n.permissionMode,restartOnUpdate:n.restartOnUpdate,scheduledDailyRestart:n.scheduledDailyRestart,...n.mode===`on-demand`?{onDemand:{keepaliveSeconds:Number(n.keepaliveSeconds)||300,idleDefinition:`no-activity`}}:{},backoff:{schedule:r(n.backoffSchedule).map(Number).filter(e=>e>0),resetAfterSeconds:Number(n.backoffResetAfterSeconds)||600},...n.channelId.trim()?{binding:{type:`channel`,channelId:n.channelId.trim()}}:{}};i.backoff.schedule.length||(i.backoff.schedule=[5,15,60,300]);try{await o(`PUT`,`/spawn-policy/`+encodeURIComponent(i.name),i),e({policyModal:{...n,open:!1}}),await t().fetchManagedPolicies()}catch(e){t().showError(`Save Failed`,e.message)}},deletePolicy(e){t().openConfirm(`Delete Policy`,`Delete managed agent policy "${e}"? This will stop any running agent.`,async()=>{try{await o(`DELETE`,`/spawn-policy/`+encodeURIComponent(e)),await t().fetchManagedPolicies()}catch(e){t().showError(`Delete Failed`,e.message)}})},async browsePolicyDirectory(n){let r=t().policyModal.orchestratorId;if(!r)return;let i=t().policyDirBrowser;e({policyDirBrowser:{...i,loading:!0,error:``}});try{let i=n?`?path=`+encodeURIComponent(n):``,a=await o(`GET`,`/orchestrators/`+encodeURIComponent(r)+`/directories`+i);e({policyDirBrowser:{open:!0,loading:!1,path:a.path||``,parent:a.parent||``,baseDir:a.baseDir||``,entries:a.entries||[],error:``},policyModal:{...t().policyModal,cwd:a.path||t().policyModal.cwd}})}catch(n){e({policyDirBrowser:{...t().policyDirBrowser,loading:!1,error:n.message}})}},selectPolicyDirectory(n){e({policyModal:{...t().policyModal,cwd:n||t().policyDirBrowser.path},policyDirBrowser:{...t().policyDirBrowser,open:!1}})},openProfileModal(t,n){let r={name:``,description:``,provider:`any`,base:`host`,instructions:{system:``,append:[],repoInstructions:`allow`,globalInstructions:`allow`},relay:{context:!0,skills:!0,plugins:!0,statusLine:!0,mcp:!0},skills:[],plugins:[],mcp:{mode:`host`},hooks:{mode:`host`},permissions:{filesystem:`host`},env:{},providerOptions:{}},i;n&&t===`duplicate`?(i=JSON.parse(JSON.stringify(n)),i.name=n.name+`-copy`,delete i.builtIn):i=n&&(t===`edit`||t===`view`)?JSON.parse(JSON.stringify(n)):r,e({profileModal:{open:!0,mode:t,profile:i}})},closeProfileModal(){e({profileModal:{...t().profileModal,open:!1}})},updateProfileModal(n){let r=t().profileModal.profile;e({profileModal:{...t().profileModal,profile:{...r,...n}}})},async saveProfile(){let{mode:n,profile:r}=t().profileModal;if(!r.name.trim()){t().showError(`Validation`,`Profile name is required.`);return}if(n!==`view`)try{await o(`PUT`,`/agent-profiles/`+encodeURIComponent(r.name.trim()),r),e({profileModal:{...t().profileModal,open:!1}}),await t().fetchAgentProfiles(),t().showNotification(`Profile "${r.name}" saved`)}catch(e){t().showError(`Save Failed`,e.message)}},deleteProfile(e){t().openConfirm(`Delete Profile`,`Delete agent profile "${e}"?`,async()=>{try{await o(`DELETE`,`/agent-profiles/`+encodeURIComponent(e)),await t().fetchAgentProfiles(),t().showNotification(`Profile "${e}" deleted`)}catch(e){t().showError(`Delete Failed`,e.message)}})}}),vt=(e,t)=>({operatorActivity:[],recordOperatorActivity(n){let r={id:Date.now(),kind:`operator`,title:n.title||`Activity`,body:n.body,meta:n.meta,icon:n.icon,view:n.view,peer:n.peer,messageId:n.messageId,pairId:n.pairId,taskId:n.taskId,agentId:n.agentId,ts:Date.now(),clientId:`op-`+Date.now(),createdAt:Date.now()};e({operatorActivity:[r,...t().operatorActivity.slice(0,79)]}),o(`POST`,`/activity`,{operatorId:y,clientId:r.clientId,kind:r.kind,title:r.title,body:r.body,meta:r.meta,icon:r.icon,view:r.view,peer:r.peer,messageId:r.messageId,pairId:r.pairId,taskId:r.taskId,agentId:r.agentId}).catch(()=>{})},async openActivityItem(e){if(e.view&&await t().switchView(e.view===`inbox`?`chat`:e.view),e.peer&&t().openInboxThread(e.peer),e.agentId){let n=t().agentsById[e.agentId];n&&t().openAgentDetail(n)}if(e.taskId){let n=t().tasks.find(t=>t.id===e.taskId);n&&await t().openTaskEvents(n)}}});function Q(e){return m(e.createdAt??e.ts)}function yt(e,t){let n=[`# Agent Relay Timeline`,``,`Exported: ${t}`,`Events: ${e.length}`,``];for(let t of e){let e=new Date(Q(t)).toISOString();n.push(`## ${t.title||t.kind||`Event`}`),n.push(`- When: ${e}`),t.kind&&n.push(`- Kind: ${t.kind}`),t.agentId&&n.push(`- Agent: ${t.agentId}`),t.peer&&n.push(`- Peer: ${t.peer}`),t.body&&n.push(``,t.body),n.push(``)}return n.join(`
|
|
8
8
|
`)}var bt=(e,t)=>({activityEvents:[],activityFilter:``,async fetchActivityEvents(){try{e({activityEvents:await o(`GET`,`/activity?limit=200`)})}catch{}},exportActivity(e){let n=t(),r=[...n.operatorActivity,...n.activityEvents].sort((e,t)=>Q(t)-Q(e)),i=new Date().toISOString(),a=`agent-relay-timeline-${i.slice(0,10)}.${e===`json`?`json`:`md`}`;e===`json`?E(a,JSON.stringify({title:`Agent Relay Timeline`,exportedAt:i,events:r},null,2),`application/json`):E(a,yt(r,i),`text/markdown`)},exportThread(e,t){let n=`agent-relay-thread-${l(e.peer)}.${t===`json`?`json`:`md`}`,r={title:`Thread: `+e.peer,importedHistory:e.importedHistory||[],messages:e.messages,exportedAt:new Date().toISOString()};E(n,JSON.stringify(r,null,2),t===`json`?`application/json`:`text/markdown`)},exportPair(e,t){let n=`agent-relay-pair-${l(e.id)}.${t===`json`?`json`:`md`}`,r={title:`Pair: `+e.id,pair:e,exportedAt:new Date().toISOString()};E(n,JSON.stringify(r,null,2),t===`json`?`application/json`:`text/markdown`)},async exportTask(n,r){let i=t().taskEventCache[n.id]||[];if(!i.length)try{i=await o(`GET`,`/tasks/`+n.id+`/events`),e({taskEventCache:{...t().taskEventCache,[n.id]:i}})}catch{}let a=`agent-relay-task-${n.id}.${r===`json`?`json`:`md`}`,s={title:`Task: `+(n.title||`#`+n.id),task:n,events:i,exportedAt:new Date().toISOString()};E(a,JSON.stringify(s,null,2),r===`json`?`application/json`:`text/markdown`)}}),xt=(e,t)=>({channels:[],connectors:[],integrations:[],automations:[],automationRuns:[],health:null,maintenanceJobs:[],analyticsPeriod:`24h`,analyticsData:null,async fetchChannels(){try{e({channels:await o(`GET`,`/channels`)})}catch{}},async fetchConnectors(){try{e({connectors:await o(`GET`,`/connectors`)})}catch{}},async fetchIntegrations(){try{e({integrations:await o(`GET`,`/integrations`)})}catch{}},async fetchAutomations(){try{e({automations:await o(`GET`,`/automations`)})}catch{}},async fetchAutomationRuns(t){try{let n=new URLSearchParams({limit:`100`});t&&n.set(`automationId`,t),e({automationRuns:await o(`GET`,`/automation-runs?`+n.toString())})}catch{}},async fetchHealth(){try{e({health:await o(`GET`,`/health`)})}catch{}},async fetchMaintenanceJobs(){try{e({maintenanceJobs:await o(`GET`,`/maintenance/jobs`)})}catch{}},async runMaintenanceJob(n){try{let r=await o(`POST`,`/maintenance/jobs/`+encodeURIComponent(n)+`/run`,{});return e({maintenanceJobs:r.jobs}),t().showNotification(r.run.status===`succeeded`?`Maintenance job completed`:`Maintenance job skipped`),r.run}catch(e){return t().showError(`Maintenance Job Failed`,e.message),await t().fetchMaintenanceJobs(),null}},async runHealthAction(n){if(n.preset&&e({agentPresetFilter:n.preset,showOffline:!0}),n.api&&n.path&&(await o(n.api,n.path),await t().refreshLiveData()),n.view&&await t().switchView(n.view),n.copy)try{await navigator.clipboard?.writeText(n.copy)}catch{}},async runConnectorAction(e,n){try{let r=await o(`POST`,`/connectors/`+encodeURIComponent(e)+`/actions`,{action:n});if(await t().fetchConnectors(),!r.ok)throw Error(r.stderr||`${n} failed`);return r}catch(e){throw t().showError(`Connector Action Failed`,e.message),e}},async fetchAnalytics(){try{e({analyticsData:await o(`GET`,`/stats/analytics?period=`+t().analyticsPeriod)})}catch{}},setAnalyticsPeriod(n){e({analyticsPeriod:n}),t().fetchAnalytics()}}),St=(e,t)=>({workspaces:[],workspaceFocusId:null,workspaceGitState:{},workspaceMergePreview:{},workspaceDiff:{},workspaceOrphans:[],async openWorkspaceFocus(n){e({workspaceFocusId:n}),await t().switchView(`workspaces`)},async fetchWorkspaces(){try{e({workspaces:await o(`GET`,`/workspaces`)})}catch{}},async fetchWorkspaceGitState(t){try{let n=await o(`GET`,`/workspaces/`+encodeURIComponent(t)+`/git-state`);e(e=>({workspaceGitState:{...e.workspaceGitState,[t]:n}}))}catch(n){e(e=>({workspaceGitState:{...e.workspaceGitState,[t]:{available:!1,reason:n.message}}}))}},async fetchWorkspaceMergePreview(t){try{let n=await o(`GET`,`/workspaces/`+encodeURIComponent(t)+`/merge-preview`);e(e=>({workspaceMergePreview:{...e.workspaceMergePreview,[t]:n}}))}catch(n){e(e=>({workspaceMergePreview:{...e.workspaceMergePreview,[t]:{available:!1,reason:n.message}}}))}},async fetchWorkspaceDiff(t){try{let n=await o(`GET`,`/workspaces/`+encodeURIComponent(t)+`/diff`);e(e=>({workspaceDiff:{...e.workspaceDiff,[t]:n}}))}catch(n){e(e=>({workspaceDiff:{...e.workspaceDiff,[t]:{available:!1,reason:n.message}}}))}},async fetchWorkspaceOrphans(){try{e({workspaceOrphans:(await o(`GET`,`/workspaces/orphans`)).orphans??[]})}catch{}},async reclaimWorkspaceOrphan(e){t().openConfirm(`Reclaim Orphan Worktree`,`Remove the orphaned worktree "${e.branch||e.worktreePath}" from disk? It has no live agent.`,async()=>{try{await o(`POST`,`/workspaces/orphans/reclaim`,{worktreePath:e.worktreePath,repoRoot:e.repoRoot,branch:e.branch}),t().showNotification(`Orphan reclaim dispatched`),await Promise.all([t().fetchWorkspaceOrphans(),t().fetchActivityEvents()])}catch(e){t().showError(`Reclaim Failed`,e.message)}})},async workspaceAction(e,n){let r=n===`ready`?`Mark ready`:n===`request-review`?`Request review`:n===`merge-plan`?`Mark merge planned`:n===`merge`?`Merge`:n===`abandon`?`Abandon`:`Cleanup`,i=async()=>{try{await o(`POST`,`/workspaces/`+encodeURIComponent(e)+`/actions`,{action:n}),t().showNotification(n===`cleanup`?`Workspace cleanup requested`:n===`merge`?`Workspace merge dispatched`:`Workspace updated: ${r}`),await Promise.all([t().fetchWorkspaces(),t().fetchOrchestrators(),t().fetchActivityEvents()])}catch(e){t().showError(`Workspace Action Failed`,e.message)}};if(n===`cleanup`||n===`abandon`||n===`merge`){let r=t().workspaces.find(t=>t.id===e),a=r?.branch||r?.worktreePath||e;if(n===`merge`){let n=t().workspaceMergePreview[e],r=n&&n.available!==!1?` — ${n.strategy===`pr`?`opens a PR`:`rebases & fast-forwards into ${n.baseRef||`base`}, then deletes the branch`}.`:` — lands the work and deletes the branch.`;t().openConfirm(`Merge Workspace`,`Merge workspace "${a}"?${r}`,i);return}if(n===`cleanup`){await t().fetchWorkspaceGitState(e);let n=t().workspaceGitState[e],r=``;if(n&&n.available!==!1&&!n.missing){let e=n.ahead??0,t=n.dirtyCount??0;(e>0||t>0)&&(r=` ⚠ This destroys ${[e>0?`${e} unmerged commit(s)`:``,t>0?`${t} uncommitted change(s)`:``].filter(Boolean).join(` and `)}.`)}t().openConfirm(`Cleanup Workspace`,`Remove the worktree for "${a}" on the host?${r}`,i);return}t().openConfirm(`Abandon Workspace`,`Abandon workspace "${a}"?`,i);return}await i()},async purgeWorkspace(e){let n=t().workspaces.find(t=>t.id===e),r=n?.branch||n?.worktreePath||e;t().openConfirm(`Purge Workspace Record`,`Permanently remove the record for "${r}"? This only clears the dashboard row — it does not touch disk.`,async()=>{try{await o(`DELETE`,`/workspaces/`+encodeURIComponent(e)),t().showNotification(`Workspace record purged`),await Promise.all([t().fetchWorkspaces(),t().fetchActivityEvents()])}catch(e){t().showError(`Purge Failed`,e.message)}})}}),Ct=(e,t)=>({memories:[],memoryTotal:0,memoryBrokerInfo:null,memoryStats:null,memoryFilters:{search:``,type:``,scope:``,tags:``,visibility:``,minRelevance:`0`},selectedMemoryId:``,memoryLoading:!1,async refreshMemory(){await Promise.all([t().fetchMemoryBroker(),t().fetchMemoryStats(),t().fetchMemories()])},async fetchMemoryBroker(){try{e({memoryBrokerInfo:await o(`GET`,`/memories/broker`)})}catch(e){t().showError(`Memory Broker Failed`,e.message)}},async fetchMemoryStats(){try{e({memoryStats:await o(`GET`,`/memories/stats`)})}catch{}},async fetchMemories(){let n=t().memoryFilters,r={limit:100};if(n.type&&(r.type=n.type),n.scope.trim()&&(r.scope=n.scope.trim()),n.visibility&&(r.visibility=n.visibility),n.tags.trim()&&(r.tags=n.tags.split(`,`).map(e=>e.trim()).filter(Boolean)),n.minRelevance.trim()!==``){let e=Number(n.minRelevance);Number.isFinite(e)&&(r.minRelevance=Math.max(0,Math.min(1,e)))}e({memoryLoading:!0});try{let n=await o(`POST`,`/memories/search`,r),i=n.memories.some(e=>e.id===t().selectedMemoryId)?t().selectedMemoryId:n.memories[0]?.id||``;e({memories:n.memories,memoryTotal:n.total,selectedMemoryId:i})}catch(e){t().showError(`Memory Search Failed`,e.message)}finally{e({memoryLoading:!1})}},async saveMemory(n,r){try{e({selectedMemoryId:(r?await o(`PATCH`,`/memories/`+encodeURIComponent(r),n):await o(`POST`,`/memories`,n)).id}),await Promise.all([t().fetchMemories(),t().fetchMemoryStats()]),t().showNotification(r?`Memory updated`:`Memory created`)}catch(e){t().showError(`Memory Save Failed`,e.message)}},deleteMemory(n){t().openConfirm(`Delete Memory`,`Delete memory "${n}"?`,async()=>{try{await o(`DELETE`,`/memories/`+encodeURIComponent(n)),e({selectedMemoryId:``}),await Promise.all([t().fetchMemories(),t().fetchMemoryStats()]),t().showNotification(`Memory deleted`)}catch(e){t().showError(`Delete Failed`,e.message)}})},async injectMemory(e){try{let n=await o(`POST`,`/memories/inject`,e);return t().showNotification(`Memory inject command sent to ${e.agentId}`),n}catch(e){return t().showError(`Memory Inject Failed`,e.message),null}}}),$=se()(ue((...e)=>({...nt(...e),...rt(...e),...ct(...e),...pt(...e),...mt(...e),...ht(...e),...gt(...e),..._t(...e),...Qe(...e),...vt(...e),...bt(...e),...$e(...e),...xt(...e),...St(...e),...Ct(...e)}),{name:`agent-relay-dashboard`,partialize:e=>({theme:e.theme,view:e.view,showOffline:e.showOffline,showBuiltIns:e.showBuiltIns,showReasoning:e.showReasoning,autoRefresh:e.autoRefresh,voiceTtsEnabled:e.voiceTtsEnabled,voiceTtsLang:e.voiceTtsLang,voiceTtsMode:e.voiceTtsMode,voiceTtsKokoroVoice:e.voiceTtsKokoroVoice,voiceTtsBrowserVoice:e.voiceTtsBrowserVoice,voiceInputMode:e.voiceInputMode,agentSort:e.agentSort,agentSortDir:e.agentSortDir,agentPresetFilter:e.agentPresetFilter,agentStatusFilter:e.agentStatusFilter,agentTagFilter:e.agentTagFilter,agentHostFilter:e.agentHostFilter,pairStatusFilter:e.pairStatusFilter,inboxSort:e.inboxSort,inboxSortDir:e.inboxSortDir,inboxShowArchived:e.inboxShowArchived,chatAgentProviderFilter:e.chatAgentProviderFilter,chatAgentStatusFilter:e.chatAgentStatusFilter,chatAgentTagFilter:e.chatAgentTagFilter,chatAgentCapFilter:e.chatAgentCapFilter,chatAgentHostFilter:e.chatAgentHostFilter,chatAgentSort:e.chatAgentSort,chatAgentSortDir:e.chatAgentSortDir,chatAgentGroupBy:e.chatAgentGroupBy,chatAgentFiltersCollapsed:e.chatAgentFiltersCollapsed,planCollapsed:e.planCollapsed,activityFilter:e.activityFilter,analyticsPeriod:e.analyticsPeriod,memoryFilters:e.memoryFilters,authToken:e.authToken,inboxReadCursors:e.inboxReadCursors,inboxArchivedThreads:e.inboxArchivedThreads,inboxDrafts:e.inboxDrafts,chatStatusEvents:e.chatStatusEvents,operatorActivity:e.operatorActivity,notifications:e.notifications,notificationUnread:e.notificationUnread,notificationSettings:e.notificationSettings,spawnOrchId:e.spawnOrchId,spawnProvider:e.spawnProvider,spawnModel:e.spawnModel,spawnEffort:e.spawnEffort,spawnProfile:e.spawnProfile,spawnCwd:e.spawnCwd,spawnApproval:e.spawnApproval,spawnWorkspaceMode:e.spawnWorkspaceMode,spawnCwdHistory:e.spawnCwdHistory})}));$.subscribe(tt);export{P as a,xe as c,we as d,De as f,V as i,Ee as l,X as n,Oe as o,N as p,Z as r,ke as s,$ as t,Ce as u};
|
|
9
|
-
//# sourceMappingURL=store-
|
|
9
|
+
//# sourceMappingURL=store-DmxnYVm1.js.map
|