@makinbakin/sdk 0.0.1-rc.28 → 0.0.1-rc.29

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.
@@ -14,9 +14,8 @@ interface Return {
14
14
  /**
15
15
  * Resize a right-anchored panel by dragging its left edge. The handle lives at
16
16
  * the left of the element; dragging left grows the panel, dragging right
17
- * shrinks it. Keyboard: ArrowLeft/ArrowRight (Shift for a larger step). The
18
- * companion to {@link useVerticalResize} for side-by-side split panes; both are
19
- * thin wrappers over {@link useResizablePane}.
17
+ * shrinks it. Keyboard: ArrowLeft/ArrowRight (Shift for a larger step).
18
+ * Thin wrapper over {@link useResizablePane} for side-by-side split panes.
20
19
  */
21
20
  export declare function useHorizontalResize({ defaultWidth, minWidth, maxWidth, storageKey }: Options): Return;
22
21
  export {};
@@ -1,8 +1,8 @@
1
1
  /**
2
- * Shared core for the two split-pane resize hooks. A pane is anchored to the
2
+ * Shared split-pane resize behavior. A pane is anchored to the
3
3
  * trailing edge (bottom for 'y', right for 'x') and resized by dragging the
4
4
  * divider on its leading edge — dragging toward that edge (up / left) grows it.
5
- * {@link useVerticalResize} and {@link useHorizontalResize} are thin wrappers;
5
+ * {@link useHorizontalResize} provides the right-anchored panel wrapper;
6
6
  * keep all drag / persistence / a11y logic here so it lives in exactly one place.
7
7
  */
8
8
  export type ResizeAxis = 'x' | 'y';
@@ -237,7 +237,9 @@ export type ChatChunk =
237
237
  data?: RuntimeMetadata;
238
238
  usage?: MessageUsage;
239
239
  }
240
- /** Terminal failure — `data.kind` carries the RuntimeError kind when known. */
240
+ /** Terminal failure — `data.kind` carries the RuntimeError kind when known;
241
+ * `data.model` names the qualified model id when the failure was the
242
+ * provider rejecting that model (kind 'model_not_supported', #852). */
241
243
  | {
242
244
  type: 'error';
243
245
  content?: string;
@@ -832,6 +834,18 @@ export interface AgentRuntimeAdapter {
832
834
  listAvailable(opts?: {
833
835
  includeUnavailable?: boolean;
834
836
  }): Promise<RuntimeAvailableModel[]>;
837
+ /**
838
+ * OPTIONAL capability (#852): verify the ACCOUNT can actually call this
839
+ * model by firing a minimal (~1-token) completion. Resolves on success;
840
+ * rejects with a typed RuntimeError — `model_not_supported` when the
841
+ * provider rejected the model id itself. Adapters without a cheap probe
842
+ * transport OMIT the member; callers feature-detect (`models.probe?.`).
843
+ * Billed (~pennies) and user-triggered only — never called on a
844
+ * schedule or from background refresh paths.
845
+ */
846
+ probe?(modelId: string, opts?: {
847
+ signal?: AbortSignal;
848
+ }): Promise<void>;
835
849
  /** Static declaration of which routing-policy fields this runtime honors. */
836
850
  routingSupport(): RuntimeRoutingSupport;
837
851
  /** The runtime's current routing policy (unsupported fields empty). */
@@ -18,6 +18,13 @@ export type RuntimeErrorKind =
18
18
  | 'provider_cooldown'
19
19
  /** Structured runtime failure (HTTP-status class, CLI exit, protocol). */
20
20
  | 'runtime_failed'
21
+ /**
22
+ * The provider deterministically rejected the MODEL ID for this account
23
+ * (retired/unentitled model — the #852 class). Not a cooldown: waiting
24
+ * never fixes it, so it is never retried. `providerInfo.model` carries the
25
+ * qualified rejected id; core records it as availability evidence.
26
+ */
27
+ | 'model_not_supported'
21
28
  /**
22
29
  * The caller intentionally cancelled the turn (MessageArgs.signal) —
23
30
  * terminal: never retried, never diagnosed, never enters the recovery
package/hooks/index.d.ts CHANGED
@@ -23,8 +23,6 @@ export { useContentStore } from '../_internal/app/hooks/use-content-store';
23
23
  export { useNavBadge } from '../_internal/app/hooks/use-nav-badge';
24
24
  /** Read/toggle the global debug (X-Ray) flag. */
25
25
  export { useDebug } from '../_internal/app/hooks/use-debug';
26
- /** Guard a form against unmounting while submission is in flight. */
27
- export { useFormGuard } from '../_internal/app/hooks/use-form-guard';
28
26
  /** Cancellable JSON GET with a `{ data, loading, error, refresh }` lifecycle. */
29
27
  export { useJsonFetch, usePluginJsonFetch } from '../_internal/app/hooks/use-json-fetch';
30
28
  export type { UseJsonFetchOptions, UseJsonFetchResult } from '../_internal/app/hooks/use-json-fetch';
@@ -55,17 +53,12 @@ export { useSidebar } from '../_internal/app/hooks/use-sidebar';
55
53
  export { useSSE } from '../_internal/app/hooks/use-sse';
56
54
  /** Subscribe to a server-pushed plugin event over the shell's single connection. */
57
55
  export { usePluginEvent, emitPluginEvent, type PluginEventPayload } from '../_internal/app/hooks/use-plugin-event';
58
- /** Headless drag-drop file intake (drag-over state + handlers + accept filter) — style your own zone. */
59
- export { useFileDrop } from '../_internal/app/hooks/use-file-drop';
60
- export type { UseFileDropOptions, UseFileDropResult } from '../_internal/app/hooks/use-file-drop';
61
56
  /** @deprecated Import history-aware back from `@makinbakin/sdk/navigation`. */
62
57
  export { useHistoryBack } from '../_internal/app/hooks/use-history-back';
63
58
  /** Fire a toast notification (success/error/info). */
64
59
  export { toast } from '../_internal/app/hooks/use-toast';
65
60
  /** Subscribe to the toast store for custom toast UIs. */
66
61
  export { useToastStore } from '../_internal/app/hooks/use-toast';
67
- /** Imperatively resize a vertical pane via mouse drag handle. */
68
- export { useVerticalResize } from '../_internal/app/hooks/use-vertical-resize';
69
62
  /** Resize a side-by-side split pane by dragging the divider between columns. */
70
63
  export { useHorizontalResize } from '../_internal/app/hooks/use-horizontal-resize';
71
64
  /** Access the agent registry store (Zustand). */
package/hooks/index.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // @bun
2
- var createStoreImpl=(createState)=>{let state,listeners=new Set,setState=(partial,replace)=>{let nextState=typeof partial==="function"?partial(state):partial;if(!Object.is(nextState,state)){let previousState=state;state=(replace!=null?replace:typeof nextState!=="object"||nextState===null)?nextState:Object.assign({},state,nextState),listeners.forEach((listener)=>listener(state,previousState))}},getState=()=>state,api={setState,getState,getInitialState:()=>initialState,subscribe:(listener)=>{return listeners.add(listener),()=>listeners.delete(listener)}},initialState=state=createState(setState,getState,api);return api},createStore=(createState)=>createState?createStoreImpl(createState):createStoreImpl;import React from"react";var identity=(arg)=>arg;function useStore(api,selector=identity){let slice=React.useSyncExternalStore(api.subscribe,React.useCallback(()=>selector(api.getState()),[api,selector]),React.useCallback(()=>selector(api.getInitialState()),[api,selector]));return React.useDebugValue(slice),slice}var createImpl=(createState)=>{let api=createStore(createState),useBoundStore=(selector)=>useStore(api,selector);return Object.assign(useBoundStore,api),useBoundStore},create=(createState)=>createState?createImpl(createState):createImpl;function mapAuditMessage(event,data){switch(event){case"task.dispatched":return`Dispatched: ${data.title}`;case"task.triaged":return`Triaged: ${data.title}`;case"task.created":return`Created task: ${data.title}`;case"task.deleted":return`Deleted task: ${data.title}`;case"task.moved":return`Moved "${data.title}" \u2192 ${data.to}`;case"task.assigned":return`Assigned "${data.title}" to ${data.assignee}`;case"task.blocked":return`Blocked: ${data.title} \u2014 ${data.reason||"no reason"}`;case"task.dispatch_failed":{if(data.category==="model_provider_unavailable")return"Dispatch failed: model provider unavailable";if(typeof data.summary==="string")return data.summary;if(typeof data.error==="string"&&data.error.startsWith("Dispatch failed:"))return data.error;return`Dispatch failed: ${data.error||"unknown error"}`}case"task.updated":return`Updated: ${data.title}`;case"task.routed":{let parts=[data.model,data.thinking?`thinking ${data.thinking}`:null].filter(Boolean),via=typeof data.source==="string"&&data.source!=="inherit"?` via ${data.source==="class"?"class route":String(data.source).replace(/^tag:/,'tag "')+'"'}`:"";return`Routed to ${parts.join(", ")||"override"}${via}`}case"task.completion_suppressed":return`Ignored a duplicate completion${data.title?` of "${data.title}"`:""} \u2014 ${data.firstAgent||"another run"} had already completed this task${data.firstChannel?` via ${data.firstChannel}`:""}.`;case"task.dispatch_failure_ignored":return`A session error arrived after "${data.title||data.id}" had already moved to ${data.column||"done"} \u2014 no action needed.`;case"team.message_blocked":return`Blocked a message to ${data.agentId} \u2014 they are already running task ${data.taskId}.`;case"brand.injected":return`Brand '${data.brandId}' injected into dispatch${data.cardBytes?` (${data.cardBytes} B card)`:""}`;case"brand.dispatch_blocked":return typeof data.message==="string"?data.message:`Task waiting on missing brand '${data.brandId}'`;case"brand.asset_missing":return`Brand '${data.brandId}' has missing asset references`;case"brand.created":return`Created brand '${data.brandId}'`;case"brand.updated":return`Updated brand '${data.brandId}'`;case"brand.deleted":return`Deleted brand '${data.brandId}'`;case"task.worktree_materialized":return`Working in an isolated worktree of ${typeof data.repoPath==="string"?data.repoPath.split("/").pop():"the bound repo"} on branch ${data.branch} \u2014 the branch survives after the task settles`;case"task.turn_aborted":return data.reason==="superseded"?`Stopped a stale attempt on "${data.title||data.id}" \u2014 a fresh attempt takes over`:`Stopped the in-flight attempt on "${data.title||data.id}"${data.reason?` (${data.reason})`:""}`;case"task.turn_force_released":return`Released a hung attempt on task ${data.id} \u2014 its dispatch slot is free again`;case"task.run_superseded":return`Superseded a stalled attempt on "${data.title||data.id}" \u2014 it will be re-dispatched`;case"task.repo_binding_blocked":return typeof data.error==="string"?`Task blocked: ${data.error}`:"Task blocked: repo binding failed";case"dispatch.concurrency_clamped":return`Per-agent parallelism clamped to 1: the active runtime cannot isolate same-agent turns (requested ${data.requested})`;case"asset.stale_run_write_suppressed":return`Recorded a late save from a superseded run as version ${data.version} of ${data.assetId} WITHOUT promoting it \u2014 the current deliverable is unchanged`;case"system.init":return"Bakin started";case"system.dispatch_error":return`Dispatch failed: ${data.error||"unknown error"}`;case"workflow.step_dispatched":return`Step "${data.label||"unknown"}" dispatched to ${data.agent||"agent"}`;case"workflow.step_complete":return`Step "${data.label||"unknown"}" completed`;case"workflow.gate_reached":return`Awaiting approval: ${data.label||"gate"}`;case"workflow.gate_approved":return`Approved: ${data.label||"gate"}`;case"workflow.gate_rejected":return`Rejected: ${data.label||"gate"}${data.reason?` \u2014 ${data.reason}`:""}`;case"workflow.complete":return`Workflow complete${data.workflowId?` (${data.workflowId})`:""}`;default:{if(typeof data.message==="string"&&data.message.trim())return data.message;if(event.startsWith("exec.")){let suffix=event.endsWith(".fail")?" (failed)":event.endsWith(".error")?" (error)":"";if(data.label)return`${data.label}${suffix}`;let toolName=event.replace(/^exec\./,"").replace(/\.(ok|fail|error)$/,"");return humanizeExecName(toolName)+suffix}return event}}}function humanizeExecName(name){let words=name.replace(/^bakin_exec_/,"").split("_");if(words.length===0)return name;return words[0]=words[0].charAt(0).toUpperCase()+words[0].slice(1),words.join(" ")}function isNoisyEvent(evt){if(evt.agent==="system"&&evt.message.startsWith("Dispatch failed"))return!0;if(evt.eventName&&isReadOnlyExecOk(evt.eventName))return!0;if(evt.eventName==="dispatch.registry_clobber")return!0;return!1}function isReadOnlyExecOk(eventName){if(!eventName.startsWith("exec.")||!eventName.endsWith(".ok"))return!1;let toolName=eventName.replace(/^exec\./,"").replace(/\.ok$/,"");if(toolName==="bakin_exec_get_paths"||toolName==="bakin_exec_heartbeat")return!0;return/_(list|get|query|search)$/.test(toolName)}var useContentStore=create((set,get)=>({files:{},heartbeats:{},connected:!1,loading:!0,auditEntries:[],activityEvents:[],sseConnected:!1,debug:!1,setFiles:(files)=>set({files}),updateFile:(key,content)=>set((state)=>({files:{...state.files,[key]:content}})),setHeartbeats:(heartbeats)=>set({heartbeats}),setConnected:(connected)=>set({connected}),appendAuditEntry:(entry)=>set((state)=>({auditEntries:[...state.auditEntries,entry]})),appendActivityEvent:(event)=>set((state)=>{if(isNoisyEvent(event))return state;if(state.activityEvents.some((e)=>e.id===event.id))return state;return{activityEvents:[event,...state.activityEvents].slice(0,100)}}),setActivityEvents:(events)=>set({activityEvents:events.filter((e)=>!isNoisyEvent(e)).slice(0,100)}),setSseConnected:(connected)=>set({sseConnected:connected}),setDebug:(debug)=>{set({debug});try{localStorage.setItem("bakin-debug",String(debug))}catch{}},toggleDebug:()=>{let next=!get().debug;set({debug:next});try{localStorage.setItem("bakin-debug",String(next))}catch{}},initialize:async()=>{try{if(localStorage.getItem("bakin-debug")==="true")set({debug:!0})}catch{}try{let[stateRes,healthRes,activityRes]=await Promise.all([fetch("/api/state"),fetch("/api/agents/health"),fetch("/api/activity")]);if(stateRes.ok){let files=await stateRes.json();set({files})}if(healthRes.ok){let heartbeats=await healthRes.json();set({heartbeats})}if(activityRes.ok){let data=await activityRes.json();if(data?.events)get().setActivityEvents(data.events)}}catch{}finally{set({loading:!1})}}}));import{useEffect}from"react";function buildNavItemsSnapshot(registry){let items=[];for(let[pluginId,navItems]of registry.manifestNavByPlugin.entries()){if(registry.navByPlugin.has(pluginId))continue;items.push(...navItems)}for(let navItems of registry.navByPlugin.values())items.push(...navItems);return items.sort((a,b)=>(a.order??100)-(b.order??100))}function getRegistry(){let g=globalThis;if(!g.__bakinClientRegistry)g.__bakinClientRegistry={navByPlugin:new Map,manifestNavByPlugin:new Map,routesByPlugin:new Map,cleanupByPlugin:new Map,navItemsSnapshot:[],version:0,listeners:new Set,badgesByPlugin:new Map,badgesSnapshot:new Map,badgeListeners:new Set,hitRenderersByPlugin:new Map,hitRenderersSnapshot:new Map,hitRendererListeners:new Set};let registry=g.__bakinClientRegistry;if(!registry.manifestNavByPlugin)registry.manifestNavByPlugin=new Map;if(!Array.isArray(registry.navItemsSnapshot))registry.navItemsSnapshot=buildNavItemsSnapshot(registry);if(!registry.badgesByPlugin)registry.badgesByPlugin=new Map;if(!registry.badgesSnapshot)registry.badgesSnapshot=buildBadgesSnapshot(registry);if(!registry.badgeListeners)registry.badgeListeners=new Set;if(!registry.hitRenderersByPlugin)registry.hitRenderersByPlugin=new Map;if(!registry.hitRenderersSnapshot)registry.hitRenderersSnapshot=buildHitRenderersSnapshot(registry);if(!registry.hitRendererListeners)registry.hitRendererListeners=new Set;return registry}function buildHitRenderersSnapshot(registry){let snapshot=new Map;for(let byType of registry.hitRenderersByPlugin.values())for(let[type,renderer]of byType)if(!snapshot.has(type))snapshot.set(type,renderer);return snapshot}function buildBadgesSnapshot(registry){let snapshot=new Map;for(let byNavItemId of registry.badgesByPlugin.values())for(let[navItemId,badge]of byNavItemId)if(!snapshot.has(navItemId))snapshot.set(navItemId,badge);return snapshot}function bumpBadges(){let registry=getRegistry();registry.badgesSnapshot=buildBadgesSnapshot(registry);for(let l of registry.badgeListeners)try{l()}catch(err){console.error("[bakin] badge listener threw:",err)}}function setNavBadge(pluginId,navItemId,badge){let registry=getRegistry(),plugin=registry.badgesByPlugin.get(pluginId);if(badge===null){if(!plugin?.has(navItemId))return;if(plugin.delete(navItemId),plugin.size===0)registry.badgesByPlugin.delete(pluginId);bumpBadges();return}let prev=plugin?.get(navItemId);if(prev&&prev.count===badge.count&&prev.tone===badge.tone)return;if(!plugin)plugin=new Map,registry.badgesByPlugin.set(pluginId,plugin);plugin.set(navItemId,{count:badge.count,tone:badge.tone}),bumpBadges()}function useNavBadge(pluginId,navItemId,badge){let key=badge?`${badge.count??""}:${badge.tone??""}`:"null";useEffect(()=>{setNavBadge(pluginId,navItemId,badge)},[pluginId,navItemId,key])}function useDebug(){let debug=useContentStore((s)=>s.debug),toggleDebug=useContentStore((s)=>s.toggleDebug);return[debug,toggleDebug]}import{useEffect as useEffect2}from"react";function useFormGuard(isDirty){useEffect2(()=>{if(!isDirty)return;let handler=(e)=>{e.preventDefault()};return window.addEventListener("beforeunload",handler),()=>window.removeEventListener("beforeunload",handler)},[isDirty])}import{useCallback,useEffect as useEffect3,useRef,useState}from"react";function useJsonFetch(url,opts){let[data,setData]=useState(null),[loading,setLoading]=useState(url!==null),[error,setError]=useState(null),[nonce,setNonce]=useState(0),refresh=useCallback(()=>setNonce((n)=>n+1),[]),optsRef=useRef(opts);return optsRef.current=opts,useEffect3(()=>{if(url===null){setData(null),setLoading(!1),setError(null);return}let controller=new AbortController,{timeoutMs,...init}=optsRef.current??{},timedOut=!1,rejectDeadline=null,deadline=timeoutMs!==void 0&&timeoutMs>0?setTimeout(()=>{timedOut=!0,controller.abort(),rejectDeadline?.(Error("Request timed out"))},timeoutMs):null,clearDeadline=()=>{if(deadline!==null)clearTimeout(deadline);rejectDeadline=null},cancelled=!1;setLoading(!0),setError(null);let request=fetch(url,{...init,signal:controller.signal}).then(async(res)=>{if(!res.ok)throw Error(`Request failed (${res.status})`);return await res.json()});return(deadline===null?request:Promise.race([request,new Promise((_resolve,reject)=>{rejectDeadline=reject})])).then((json)=>{if(clearDeadline(),cancelled)return;if(timedOut){setError("Request timed out"),setLoading(!1);return}setData(json),setLoading(!1)}).catch((err)=>{if(clearDeadline(),cancelled)return;if(timedOut){setError("Request timed out"),setLoading(!1);return}if(err?.name==="AbortError")return;setError(err instanceof Error?err.message:"Request failed"),setLoading(!1)}),()=>{cancelled=!0,clearDeadline(),controller.abort()}},[url,nonce]),{data,loading,error,refresh}}function usePluginJsonFetch(pluginId,path,opts){let clean=path===null?null:path.startsWith("/")?path.slice(1):path;return useJsonFetch(clean===null?null:`/api/plugins/${pluginId}/${clean}`,opts)}import{useState as useState2,useEffect as useEffect4,useCallback as useCallback2}from"react";function useRuntimeStatus(){let[restartNeeded,setRestartNeeded]=useState2(!1),[restarting,setRestarting]=useState2(!1);useEffect4(()=>{fetch("/api/plugins/models/runtime/status").then((r)=>{if(!r.ok)throw Error(`Runtime status: ${r.status}`);return r.json()}).then((data)=>{if(data?.restartNeeded)setRestartNeeded(!0)}).catch((e)=>console.error("Failed to fetch runtime status:",e))},[]);let restart=useCallback2(async()=>{setRestarting(!0);try{if((await fetch("/api/plugins/models/runtime/restart",{method:"POST"})).ok)setRestartNeeded(!1)}finally{setRestarting(!1)}},[]),markDirty=useCallback2(()=>setRestartNeeded(!0),[]);return{restartNeeded,restarting,restart,markDirty}}import{useLocation,useNavigate,useParams as useTanstackParams}from"@tanstack/react-router";import{useMemo}from"react";function toNavigationOptions(url){let hashIndex=url.indexOf("#"),beforeHash=hashIndex>=0?url.slice(0,hashIndex):url,hash=hashIndex>=0?url.slice(hashIndex+1):"",queryIndex=beforeHash.indexOf("?"),to=queryIndex>=0?beforeHash.slice(0,queryIndex):beforeHash,query=queryIndex>=0?beforeHash.slice(queryIndex+1):"",search=Object.create(null);for(let[key,raw]of new URLSearchParams(query))search[key]=raw;return{to,search,hash}}function useRouter(){let navigate=useNavigate();return useMemo(()=>({push:(url,options)=>{navigate({...toNavigationOptions(url),...options?.scroll===!1?{resetScroll:!1}:{}})},replace:(url)=>{navigate({...toNavigationOptions(url),replace:!0,resetScroll:!1})},back:()=>{if(typeof window<"u")window.history.back()},forward:()=>{if(typeof window<"u")window.history.forward()},refresh:()=>{if(typeof window<"u")window.location.reload()},prefetch:()=>{}}),[navigate])}function usePathname(){return useLocation().pathname}function useSearchParams(){let location=useLocation();return useMemo(()=>{let search=location.searchStr;if(typeof search==="string")return new URLSearchParams(search.startsWith("?")?search.slice(1):search);let parsed=location.search;if(parsed&&typeof parsed==="object"){let params=new URLSearchParams;for(let[key,value]of Object.entries(parsed)){if(value===void 0||value===null)continue;params.set(key,String(value))}return params}return new URLSearchParams},[location])}function useParams(){return useTanstackParams({strict:!1})}import{useCallback as useCallback3,useMemo as useMemo2,useRef as useRef2}from"react";var pendingPatch=new Map,pendingPush=!1,pendingNav=null,flushScheduled=!1;function enqueueParamUpdate(key,value,push,router,pathname){if(pendingPatch.set(key,value),pendingPush=pendingPush||push,pendingNav={router,pathname},flushScheduled)return;flushScheduled=!0,queueMicrotask(()=>{let navigation=pendingNav,usePush=pendingPush,patch=new Map(pendingPatch);pendingPatch.clear(),pendingPush=!1,pendingNav=null,flushScheduled=!1;let params=new URLSearchParams(window.location.search);for(let[patchKey,patchValue]of patch)if(patchValue===null)params.delete(patchKey);else params.set(patchKey,patchValue);let query=params.toString(),url=query?`${navigation.pathname}?${query}`:navigation.pathname;if(usePush)navigation.router.push(url,{scroll:!1});else navigation.router.replace(url,{scroll:!1})})}function useQueryState(key,defaultValue=""){let searchParams=useSearchParams(),router=useRouter(),pathname=usePathname(),pathnameRef=useRef2(pathname);pathnameRef.current=pathname;let value=searchParams.get(key)??defaultValue,setValue=useCallback3((next)=>{enqueueParamUpdate(key,next===defaultValue?null:next,!1,router,pathnameRef.current)},[key,defaultValue,router]),pushValue=useCallback3((next)=>{enqueueParamUpdate(key,next===defaultValue?null:next,!0,router,pathnameRef.current)},[key,defaultValue,router]);return[value,setValue,pushValue]}function useQueryArrayState(key){let searchParams=useSearchParams(),router=useRouter(),pathname=usePathname(),pathnameRef=useRef2(pathname);pathnameRef.current=pathname;let value=useMemo2(()=>{let raw=searchParams.get(key);return raw?raw.split(",").filter(Boolean):[]},[searchParams,key]),setValue=useCallback3((next)=>{enqueueParamUpdate(key,next.length===0?null:next.join(","),!1,router,pathnameRef.current)},[key,router]);return[value,setValue]}import{useNavigate as useNavigate2,useRouter as useTanStackRouter}from"@tanstack/react-router";import{useCallback as useCallback4}from"react";function useHistoryBack(fallbackTo){let router=useTanStackRouter(),navigate=useNavigate2();return useCallback4(()=>{if(router.history.canGoBack())router.history.back();else navigate({to:fallbackTo})},[router,navigate,fallbackTo])}import{useState as useState3,useEffect as useEffect5,useCallback as useCallback5,useRef as useRef3}from"react";function useScheduleJobs(options={}){let[jobs,setJobs]=useState3([]),[loading,setLoading]=useState3(!0),[fetchFailed,setFetchFailed]=useState3(!1),optionsRef=useRef3(options);optionsRef.current=options;let fetchJobs=useCallback5(async()=>{try{let res=await fetch("/api/plugins/schedule/");if(res.ok){let data=await res.json();setJobs(data.jobs||[]),setFetchFailed(!1)}else setFetchFailed(!0)}catch{setFetchFailed(!0)}finally{setLoading(!1)}},[]);useEffect5(()=>{fetchJobs()},[fetchJobs]),useEffect5(()=>{let es=new EventSource("/api/events"),handler=(event)=>{try{let data=JSON.parse(event.data);if(data.type==="activity"&&data.message?.includes("Schedule")||data.event?.startsWith("schedule."))fetchJobs()}catch{}};return es.addEventListener("message",handler),()=>{es.removeEventListener("message",handler),es.close()}},[fetchJobs]);let opts=options,filtered=jobs.filter((j)=>{if(opts.agent&&j.agentId!==opts.agent)return!1;return!0}),pauseJob=useCallback5(async(jobId,pauseUntil)=>{try{let res=await fetch(`/api/plugins/schedule/${jobId}/pause`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:"pause",pauseUntil})});if(res.ok)fetchJobs();return res.ok}catch{return!1}},[fetchJobs]),resumeJob=useCallback5(async(jobId)=>{try{let res=await fetch(`/api/plugins/schedule/${jobId}/pause`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:"resume"})});if(res.ok)fetchJobs();return res.ok}catch{return!1}},[fetchJobs]),deleteJob=useCallback5(async(jobId)=>{try{let res=await fetch(`/api/plugins/schedule/${jobId}`,{method:"DELETE",headers:{"Content-Type":"application/json"}});if(res.ok)setJobs((prev)=>prev.filter((j)=>j.id!==jobId));return res.ok}catch{return!1}},[]),runNow=useCallback5(async(jobId)=>{try{return(await fetch(`/api/plugins/schedule/${jobId}/run`,{method:"POST",headers:{"Content-Type":"application/json"}})).ok}catch{return!1}},[]),updateJob=useCallback5(async(jobId,data)=>{try{let res=await fetch(`/api/plugins/schedule/${jobId}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(data)});if(res.ok)fetchJobs();return res.ok}catch{return!1}},[fetchJobs]),adoptJob=useCallback5(async(jobId,data)=>{try{let res=await fetch(`/api/plugins/schedule/${jobId}/adopt`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(data)});if(res.ok)fetchJobs();return res.ok}catch{return!1}},[fetchJobs]),restoreNative=useCallback5(async(jobId)=>{try{let res=await fetch(`/api/plugins/schedule/${jobId}/restore-native`,{method:"POST",headers:{"Content-Type":"application/json"}});if(res.ok)fetchJobs();return res.ok}catch{return!1}},[fetchJobs]),skipNext=useCallback5(async(jobId,n=1)=>{try{let res=await fetch(`/api/plugins/schedule/${jobId}/pause`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:"skip",skipN:n})});if(res.ok)fetchJobs();return res.ok}catch{return!1}},[fetchJobs]),duplicateJob=useCallback5(async(jobId,overrides={})=>{let source=jobs.find((j)=>j.id===jobId);if(!source)return!1;try{let res=await fetch("/api/plugins/schedule/",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:overrides.name??`${source.displayName} (copy)`,schedule:overrides.schedule??source.humanSchedule,agentId:overrides.agentId??source.agentId,teamId:overrides.teamId??source.teamId,taskPrompt:overrides.taskPrompt??source.taskPrompt,taskTitle:overrides.taskTitle??source.taskTitle,workflowId:overrides.workflowId??source.workflowId,owner:overrides.owner??source.owner,requireTriage:overrides.requireTriage??source.requireTriage,allowOverlap:overrides.allowOverlap??source.allowOverlap,maxFailures:overrides.maxFailures??source.maxFailures,...overrides})});if(res.ok)fetchJobs();return res.ok}catch{return!1}},[jobs,fetchJobs]);return{jobs:filtered,allJobs:jobs,loading,fetchFailed,refresh:fetchJobs,pauseJob,resumeJob,deleteJob,runNow,updateJob,adoptJob,restoreNative,skipNext,duplicateJob}}function useOccurrences(fromIso,toIso){let[occurrences,setOccurrences]=useState3([]),[events,setEvents]=useState3([]),[unevaluated,setUnevaluated]=useState3([]),[droppedProviders,setDroppedProviders]=useState3([]),[loading,setLoading]=useState3(!0),fetchOccurrences=useCallback5(async()=>{try{let res=await fetch(`/api/plugins/schedule/occurrences?from=${encodeURIComponent(fromIso)}&to=${encodeURIComponent(toIso)}`);if(res.ok){let data=await res.json();setOccurrences(data.occurrences||[]),setEvents(data.events||[]),setUnevaluated(data.unevaluated||[]),setDroppedProviders(data.droppedProviders||[])}}catch{}finally{setLoading(!1)}},[fromIso,toIso]);return useEffect5(()=>{fetchOccurrences()},[fetchOccurrences]),useEffect5(()=>{let es=new EventSource("/api/events"),handler=(event)=>{try{let data=JSON.parse(event.data);if(data.type==="activity"&&data.message?.includes("Schedule")||data.event?.startsWith("schedule.")||data.type==="taskboard"||data.event?.endsWith(".scheduled_events_changed"))fetchOccurrences()}catch{}};return es.addEventListener("message",handler),()=>{es.removeEventListener("message",handler),es.close()}},[fetchOccurrences]),{occurrences,events,unevaluated,droppedProviders,loading,refresh:fetchOccurrences}}function useRunHistory(jobId,limit=20){let[runs,setRuns]=useState3([]),[loading,setLoading]=useState3(!1);return useEffect5(()=>{if(!jobId){setRuns([]);return}setLoading(!0),fetch(`/api/plugins/schedule/${jobId}/runs?limit=${limit}`).then((res)=>res.ok?res.json():null).then((data)=>{if(data)setRuns(data.runs||[])}).catch(()=>{}).finally(()=>setLoading(!1))},[jobId,limit]),{runs,loading}}import{useState as useState4,useEffect as useEffect6}from"react";function useTaskRunHistory(taskId,limit=50){let[runs,setRuns]=useState4([]),[outcome,setOutcome]=useState4(void 0),[loading,setLoading]=useState4(!1);return useEffect6(()=>{if(setRuns([]),setOutcome(void 0),!taskId)return;let controller=new AbortController;return setLoading(!0),fetch(`/api/plugins/tasks/${taskId}/runs?limit=${limit}`,{signal:controller.signal}).then((res)=>res.ok?res.json():null).then((data)=>{if(data)setRuns(data.runs||[]),setOutcome(data.outcome)}).catch(()=>{}).finally(()=>{if(!controller.signal.aborted)setLoading(!1)}),()=>controller.abort()},[taskId,limit]),{runs,outcome,loading}}import{useState as useState5,useEffect as useEffect7,useCallback as useCallback6,useRef as useRef4}from"react";function reorderBySearchResults(items,searchResults){if(!searchResults.length)return items;let scoreMap=new Map;for(let r of searchResults)scoreMap.set(r.id,r.score);let matched=[],unmatched=[];for(let item of items)if(scoreMap.has(item.id))matched.push(item);else unmatched.push(item);return matched.sort((a,b)=>(scoreMap.get(b.id)??0)-(scoreMap.get(a.id)??0)),[...matched,...unmatched]}function useSearch(options={}){let{plugin,limit=20,facets,types,debounce:debounceMs=250}=options,[results,setResults]=useState5([]),[aggregations,setAggregations]=useState5({}),[status,setStatus]=useState5("idle"),[error,setError]=useState5(null),[meta,setMeta]=useState5(null),abortRef=useRef4(null),timerRef=useRef4(null),mountedRef=useRef4(!0),lastQueryRef=useRef4(""),typesKey=types?.join(",");useEffect7(()=>{return mountedRef.current=!0,()=>{if(mountedRef.current=!1,abortRef.current?.abort(),timerRef.current)clearTimeout(timerRef.current)}},[]);let executeSearch=useCallback6(async(q)=>{if(!q.trim()){setResults([]),setAggregations({}),setMeta(null),setError(null),setStatus("idle");return}abortRef.current?.abort();let controller=new AbortController;abortRef.current=controller,setStatus("loading"),setError(null);try{let params=new URLSearchParams({q});if(limit)params.set("limit",String(limit));if(facets?.length)params.set("facets",facets.join(","));if(typesKey)params.set("types",typesKey);let url=plugin?`/api/plugins/${plugin}/search?${params}`:`/api/search?${params}`,res=await fetch(url,{signal:AbortSignal.any([controller.signal,AbortSignal.timeout(15000)])});if(!mountedRef.current)return;if(res.status===503){setResults([]),setAggregations({}),setMeta(null),setStatus("unavailable");return}if(!res.ok)throw Error(`Search failed: ${res.status}`);let data=await res.json();if(!mountedRef.current)return;setResults(Array.isArray(data.results)?data.results:[]),setAggregations(data.aggregations||{}),setMeta(data.meta||null),setStatus("ok")}catch(err){if(!mountedRef.current)return;if(err instanceof DOMException&&err.name==="AbortError")return;let msg=err instanceof Error?err.message:String(err);setError(msg),setResults([]),setAggregations({}),setStatus("error")}},[plugin,limit,facets,typesKey]),search=useCallback6((q)=>{if(lastQueryRef.current=q,timerRef.current)clearTimeout(timerRef.current);if(!q.trim()){setResults([]),setAggregations({}),setMeta(null),setError(null),setStatus("idle");return}setStatus("loading"),timerRef.current=setTimeout(()=>executeSearch(q),debounceMs)},[executeSearch,debounceMs]),retry=useCallback6(()=>{if(lastQueryRef.current.trim())executeSearch(lastQueryRef.current)},[executeSearch]),clear=useCallback6(()=>{if(lastQueryRef.current="",setResults([]),setAggregations({}),setMeta(null),setError(null),setStatus("idle"),abortRef.current?.abort(),timerRef.current)clearTimeout(timerRef.current)},[]);return{results,aggregations,status,loading:status==="loading",error,meta,search,clear,retry}}import{useState as useState6,useEffect as useEffect8}from"react";function useSidebar(){let[collapsed,setCollapsed]=useState6(!1);return useEffect8(()=>{if(localStorage.getItem("sidebar-collapsed")==="true")setCollapsed(!0)},[]),{collapsed,toggle:()=>setCollapsed((c)=>{return localStorage.setItem("sidebar-collapsed",String(!c)),!c})}}import{useEffect as useEffect10,useRef as useRef6}from"react";import{useEffect as useEffect9,useRef as useRef5}from"react";var subscribers=globalThis.__bakinPluginEventSubs??(globalThis.__bakinPluginEventSubs=new Map);function emitPluginEvent(payload){let event=payload?.event;if(typeof event!=="string")return;let set=subscribers.get(event);if(!set)return;for(let handler of[...set])try{handler(payload)}catch{}}function usePluginEvent(event,handler){let handlerRef=useRef5(handler);handlerRef.current=handler,useEffect9(()=>{let wrapped=(payload)=>handlerRef.current(payload),set=subscribers.get(event);if(!set)set=new Set,subscribers.set(event,set);return set.add(wrapped),()=>{if(set.delete(wrapped),set.size===0)subscribers.delete(event)}},[event])}function navigateToUrl(url){let bridge=globalThis.__bakinNavigate;if(bridge){bridge(url);return}window.location.assign(url)}function isNotificationsSupported(){return typeof window<"u"&&"Notification"in window&&window.isSecureContext}function isNotificationsEnabled(){if(!isNotificationsSupported())return!1;return localStorage.getItem("bakin-notifications-enabled")==="true"&&Notification.permission==="granted"}function sendBrowserNotification(title,body,url){if(!isNotificationsEnabled())return;if(document.hasFocus())return;let notification=new Notification(title,{body,icon:"/favicon.ico"});if(url)notification.onclick=()=>{window.focus(),navigateToUrl(url),notification.close()}}var MAX_RETRIES=20,BASE_DELAY=1000,MAX_DELAY=30000;function isDevPluginHotReloadActive(){return typeof document<"u"&&!!document.querySelector('script[src="/__bakin-dev/client.js"]')}function useSSE(){let updateFile=useContentStore((s)=>s.updateFile),setConnected=useContentStore((s)=>s.setConnected),setHeartbeats=useContentStore((s)=>s.setHeartbeats),initialize=useContentStore((s)=>s.initialize),appendAuditEntry=useContentStore((s)=>s.appendAuditEntry),appendActivityEvent=useContentStore((s)=>s.appendActivityEvent),setSseConnected=useContentStore((s)=>s.setSseConnected),esRef=useRef6(null),retryRef=useRef6(0),timeoutRef=useRef6(null),hbTimerRef=useRef6(null);useEffect10(()=>{initialize();function connect(){if(esRef.current)esRef.current.close(),esRef.current=null;let es=new EventSource("/api/events");esRef.current=es,es.onopen=()=>{setConnected(!0),setSseConnected(!0),retryRef.current=0},es.onmessage=(e)=>{try{let data=JSON.parse(e.data);if(data.type==="plugin-event")emitPluginEvent(data);if(data.type==="taskboard"){emitPluginEvent({event:"taskboard"});return}if(data.type==="turn-activity"){emitPluginEvent({...data,event:"turn-activity"});return}if(data.type==="plugin:manifest-changed"){if(!isDevPluginHotReloadActive())window.location.reload();return}if(data.type==="activity"){appendActivityEvent({id:`${data.ts}-activity-${data.agent}`,ts:data.ts,type:"log",agent:data.agent||"system",message:data.message,taskId:data.taskId});return}if(data.type==="audit"&&data.entry){let entry=data.entry,entryData=entry.data||{};if(appendAuditEntry(entry),entry.event==="doctor.run")emitPluginEvent({event:"doctor.run"});appendActivityEvent({id:`${entry.ts}-${entry.event}-${entry.agent}`,ts:entry.ts,type:"audit",agent:entry.agent||"system",message:mapAuditMessage(entry.event,entryData),taskId:entryData.taskId,taskTitle:entryData.title,eventName:entry.event,...entryData.duplicate?{duplicate:!0}:{},data:entryData})}if(data.type==="plugin-event"&&typeof data.event==="string"&&data.event.startsWith("workflow.")){if(data.event.startsWith("workflow.gate")||data.event==="workflow.complete")initialize();if(data.event==="workflow.gate_reached")sendBrowserNotification("Approval needed",data.label||"A workflow gate needs your review");appendAuditEntry({ts:data.timestamp||new Date().toISOString(),event:data.event,agent:"workflow",data:{taskId:data.taskId,label:data.label,agent:data.agent,reason:data.reason,workflowId:data.workflowId}}),appendActivityEvent({id:`${data.timestamp||new Date().toISOString()}-${data.event}-workflow`,ts:data.timestamp||new Date().toISOString(),type:"audit",agent:"workflow",message:mapAuditMessage(data.event,data),taskId:data.taskId,eventName:data.event})}if(data.type==="plugin-event"&&data.event==="budget.incident_opened")sendBrowserNotification("Budget alert",data.message||"A budget cap was reached \u2014 dispatch may be deferred","/models?tab=spend"),appendActivityEvent({id:`${data.timestamp||new Date().toISOString()}-budget-incident-${data.incidentId}`,ts:data.timestamp||new Date().toISOString(),type:"alert",agent:"system",message:data.message||"Budget incident opened",eventName:"budget.incident_opened",data:{incidentId:data.incidentId,scope:data.scope,scopeId:data.scopeId,lane:data.lane,window:data.window}});if(data.type==="plugin-event"&&data.event==="brand.dispatch_blocked")sendBrowserNotification("Brand unavailable",data.message||`A task is waiting on brand '${data.brandId}'`,`/tasks?brand=${encodeURIComponent(data.brandId||"")}`),appendActivityEvent({id:`${data.timestamp||new Date().toISOString()}-brand-blocked-${data.taskId}`,ts:data.timestamp||new Date().toISOString(),type:"alert",agent:"system",message:data.message||"Task blocked on a missing brand",eventName:"brand.dispatch_blocked",data:{taskId:data.taskId,brandId:data.brandId}});if(data.type==="alert")appendActivityEvent({id:`${data.timestamp||new Date().toISOString()}-alert-system`,ts:data.timestamp||new Date().toISOString(),type:"alert",agent:"system",message:data.message||"Watchdog alert"});if(data.type==="search.rebuild.start")emitPluginEvent({event:"search.rebuild.start",table:data.table});if(data.type==="search.rebuild.progress")emitPluginEvent({event:"search.rebuild.progress",table:data.table,indexed:data.indexed??0});if(data.type==="search.rebuild.complete")emitPluginEvent({event:"search.rebuild.complete",table:data.table,indexed:data.indexed??0});if(data.type==="reindex.batch_start")appendActivityEvent({id:`${Date.now()}-reindex-batch-start`,ts:new Date().toISOString(),type:"log",agent:"system",message:`Starting full re-index (${data.tables} table${data.tables===1?"":"s"})`});if(data.type==="reindex.batch_pulse"){let pct=data.tables_total?Math.floor(data.tables_done/data.tables_total*100):0;appendActivityEvent({id:`${Date.now()}-reindex-batch-pulse`,ts:new Date().toISOString(),type:"log",agent:"system",message:`Re-indexing\u2026 ${data.tables_done}/${data.tables_total} tables (${pct}%), ${data.indexed} documents so far`})}if(data.type==="reindex.batch_complete"){let seconds=Math.max(1,Math.round((data.elapsed_ms??0)/1000));appendActivityEvent({id:`${Date.now()}-reindex-batch-complete`,ts:new Date().toISOString(),type:"log",agent:"system",message:`Completed full re-index \u2014 ${data.indexed} documents across ${data.tables} table${data.tables===1?"":"s"} in ${seconds}s`})}if(data.file&&data.content!==void 0){if(updateFile(data.file,data.content),data.file.startsWith("heartbeats/")&&data.file.endsWith(".json")){if(hbTimerRef.current)clearTimeout(hbTimerRef.current);hbTimerRef.current=setTimeout(()=>{fetch("/api/agents/health").then((r)=>r.ok?r.json():null).then((hb)=>{if(hb)setHeartbeats(hb)}).catch(()=>{})},500)}}}catch{}},es.onerror=()=>{if(setConnected(!1),setSseConnected(!1),es.close(),esRef.current=null,retryRef.current<MAX_RETRIES){let delay=Math.min(BASE_DELAY*Math.pow(2,retryRef.current),MAX_DELAY);retryRef.current++,timeoutRef.current=setTimeout(connect,delay)}}}return connect(),()=>{if(timeoutRef.current)clearTimeout(timeoutRef.current);if(hbTimerRef.current)clearTimeout(hbTimerRef.current);esRef.current?.close(),esRef.current=null}},[updateFile,setConnected,setHeartbeats,initialize,appendAuditEntry,appendActivityEvent,setSseConnected])}import{useCallback as useCallback7,useState as useState7}from"react";function useFileDrop({accept,multiple=!1,onFiles,onRejected}){let[dragOver,setDragOver]=useState7(!1),matches=useCallback7((file)=>!accept?.length||accept.some((a)=>file.type.startsWith(a)),[accept]),onDragOver=useCallback7((e)=>{e.preventDefault(),setDragOver(!0)},[]),onDragLeave=useCallback7((e)=>{e.preventDefault(),setDragOver(!1)},[]),onDrop=useCallback7((e)=>{e.preventDefault(),setDragOver(!1);let all=Array.from(e.dataTransfer?.files??[]);if(all.length===0)return;let accepted=all.filter(matches),sliced=multiple?accepted:accepted.slice(0,1);if(sliced.length>0)onFiles(sliced);else onRejected?.(all)},[matches,multiple,onFiles,onRejected]);return{dragOver,dropProps:{onDragOver,onDragLeave,onDrop}}}var DEFAULT_DURATION={success:4000,info:4000,error:1e4},counter=0,useToastStore=create((set)=>({toasts:[],add:(toast)=>{let id=String(++counter);return set((s)=>({toasts:[...s.toasts,{...toast,id}]})),setTimeout(()=>{set((s)=>({toasts:s.toasts.filter((t)=>t.id!==id)}))},toast.duration??DEFAULT_DURATION[toast.type]),id},dismiss:(id)=>set((s)=>({toasts:s.toasts.filter((t)=>t.id!==id)}))}));function toast(message,type="info",duration){return useToastStore.getState().add({message,type,...duration?{duration}:{}})}import{useCallback as useCallback8,useEffect as useEffect11,useRef as useRef7,useState as useState8}from"react";var KEY_STEP=16,KEY_STEP_LARGE=64;function clamp(n,min,max){return Math.min(max,Math.max(min,n))}function readStored(def,min,max,prefix,storageKey){if(!storageKey||typeof window>"u")return clamp(def,min,max);try{let raw=window.localStorage.getItem(prefix+storageKey);if(!raw)return clamp(def,min,max);let parsed=Number.parseInt(raw,10);return Number.isFinite(parsed)?clamp(parsed,min,max):clamp(def,min,max)}catch(err){return console.error("useResizablePane: failed to read stored size",err),clamp(def,min,max)}}function useResizablePane({axis,defaultSize,minSize,maxSize,storageKey,storagePrefix}){let[size,setSizeState]=useState8(()=>readStored(defaultSize,minSize,maxSize,storagePrefix,storageKey)),sizeRef=useRef7(size),dragging=useRef7(!1),dragStart=useRef7(0),dragStartSize=useRef7(0),persist=useCallback8((n)=>{if(!storageKey||typeof window>"u")return;try{window.localStorage.setItem(storagePrefix+storageKey,String(clamp(n,minSize,maxSize)))}catch(err){console.error("useResizablePane: failed to persist size",err)}},[storageKey,storagePrefix,minSize,maxSize]),setSize=useCallback8((n)=>{let next=clamp(n,minSize,maxSize);sizeRef.current=next,setSizeState(next),persist(next)},[minSize,maxSize,persist]);useEffect11(()=>{let clamped=clamp(sizeRef.current,minSize,maxSize);if(clamped!==sizeRef.current)setSize(clamped)},[minSize,maxSize,setSize]);let beginDrag=useCallback8((client)=>{dragging.current=!0,dragStart.current=client,dragStartSize.current=sizeRef.current},[]),onMove=useCallback8((client)=>{if(!dragging.current)return;let delta=dragStart.current-client,next=clamp(dragStartSize.current+delta,minSize,maxSize);sizeRef.current=next,setSizeState(next)},[minSize,maxSize]),endDrag=useCallback8(()=>{if(!dragging.current)return;dragging.current=!1,persist(sizeRef.current),document.body.style.cursor="",document.body.style.userSelect=""},[persist]),onMouseDown=useCallback8((e)=>{e.preventDefault(),beginDrag(axis==="x"?e.clientX:e.clientY);let move=(ev)=>onMove(axis==="x"?ev.clientX:ev.clientY),up=()=>{document.removeEventListener("mousemove",move),document.removeEventListener("mouseup",up),endDrag()};document.addEventListener("mousemove",move),document.addEventListener("mouseup",up),document.body.style.cursor=axis==="x"?"col-resize":"row-resize",document.body.style.userSelect="none"},[axis,beginDrag,onMove,endDrag]),onTouchStart=useCallback8((e)=>{let touch=e.touches[0];if(!touch)return;beginDrag(axis==="x"?touch.clientX:touch.clientY);let move=(ev)=>{let t=ev.touches[0];if(!t)return;ev.preventDefault(),onMove(axis==="x"?t.clientX:t.clientY)},up=()=>{document.removeEventListener("touchmove",move),document.removeEventListener("touchend",up),document.removeEventListener("touchcancel",up),endDrag()};document.addEventListener("touchmove",move,{passive:!1}),document.addEventListener("touchend",up),document.addEventListener("touchcancel",up)},[axis,beginDrag,onMove,endDrag]),onKeyDown=useCallback8((e)=>{let growKey=axis==="x"?"ArrowLeft":"ArrowUp",shrinkKey=axis==="x"?"ArrowRight":"ArrowDown",dir=0;if(e.key===growKey)dir=1;else if(e.key===shrinkKey)dir=-1;else return;e.preventDefault();let step=e.shiftKey?KEY_STEP_LARGE:KEY_STEP;setSize(sizeRef.current+dir*step)},[axis,setSize]);return{size,setSize,handleProps:{role:"separator",tabIndex:0,"aria-orientation":axis==="x"?"vertical":"horizontal","aria-valuenow":size,"aria-valuemin":minSize,"aria-valuemax":maxSize,onMouseDown,onTouchStart,onKeyDown}}}function useVerticalResize({defaultHeight,minHeight,maxHeight,storageKey}){let{size,setSize,handleProps}=useResizablePane({axis:"y",defaultSize:defaultHeight,minSize:minHeight,maxSize:maxHeight,storageKey,storagePrefix:"bakin-vresize:"});return{height:size,setHeight:setSize,handleProps}}function useHorizontalResize({defaultWidth,minWidth,maxWidth,storageKey}){let{size,setSize,handleProps}=useResizablePane({axis:"x",defaultSize:defaultWidth,minSize:minWidth,maxSize:maxWidth,storageKey,storagePrefix:"bakin-hresize:"});return{width:size,setWidth:setSize,handleProps}}async function parsePackageStatesResponse(res){if(!res||!res.ok)return{};try{let body=await res.json();if(!body.ok||!Array.isArray(body.agents))return{};let map={};for(let row of body.agents)map[row.agentId]=row;return map}catch{return{}}}var ROSTER_CACHE_KEY="bakin-agent-roster-v1";function readRosterCache(){try{if(typeof window>"u")return null;let raw=window.localStorage.getItem(ROSTER_CACHE_KEY);if(!raw)return null;let parsed=JSON.parse(raw);if(!Array.isArray(parsed.agents))return null;return{agents:parsed.agents.filter((a)=>!!a&&typeof a==="object"&&typeof a.id==="string"&&typeof a.name==="string"),displaySettings:parsed.displaySettings&&typeof parsed.displaySettings==="object"?parsed.displaySettings:{},mainAgentId:typeof parsed.mainAgentId==="string"?parsed.mainAgentId:null}}catch{return null}}function writeRosterCache(cache){try{window.localStorage.setItem(ROSTER_CACHE_KEY,JSON.stringify(cache))}catch{}}var hydrated=readRosterCache(),hydratedMap={};for(let a of hydrated?.agents??[])hydratedMap[a.id]=a;var useAgentStore=create((set,get)=>({agents:hydrated?.agents??[],agentIds:(hydrated?.agents??[]).map((a)=>a.id),agentMap:hydratedMap,agentsWithStatus:[],displaySettings:hydrated?.displaySettings??{},teams:[],packageStates:{},mainAgentId:hydrated?.mainAgentId??null,loaded:!1,load:async()=>{try{let[rosterRes,pkgRes]=await Promise.all([fetch("/api/plugins/team/"),fetch("/api/agent-packages?check=1").catch(()=>null)]);if(!rosterRes.ok){set({loaded:!0});return}let data=await rosterRes.json(),agents=data.agents.map(({status:_status,heartbeat:_heartbeat,heartbeatAge:_heartbeatAge,model:_model,...meta})=>meta),agentMap={};for(let a of agents)agentMap[a.id]=a;let packageStates=await parsePackageStatesResponse(pkgRes);set({agents,agentIds:agents.map((a)=>a.id),agentMap,agentsWithStatus:data.agents,displaySettings:data.displaySettings,teams:data.teams??[],packageStates,mainAgentId:data.mainAgentId??null,loaded:!0}),writeRosterCache({agents,displaySettings:data.displaySettings,mainAgentId:data.mainAgentId??null})}catch{set({loaded:!0})}},refreshPackageStates:async()=>{let res=await fetch("/api/agent-packages?check=1").catch(()=>null),packageStates=await parsePackageStatesResponse(res);set({packageStates})},updateDisplay:async(agentId,patch)=>{let current=get().displaySettings,updated={...current,[agentId]:{...current[agentId],...patch}};set({displaySettings:updated}),await fetch("/api/plugins/team/settings",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(updated)})}}));function useAgent(agentId){return useAgentStore((s)=>s.agentMap[agentId])}function useAgentList(){return useAgentStore((s)=>s.agents)}function useAgentColor(agentId){return useAgentStore((s)=>s.displaySettings[agentId]?.accentColor??"#a1a1aa")}function usePackageState(agentId){return useAgentStore((s)=>s.packageStates?.[agentId])}function useAgentDisplayName(agentId){return useAgentStore((s)=>s.displaySettings[agentId]?.displayName)}function useAgentIds(){return useAgentStore((s)=>s.agentIds)}function useMainAgentId(){return useAgentStore((s)=>s.mainAgentId)}function hexToMuted(hex,opacity=0.2){let r=parseInt(hex.slice(1,3),16),g=parseInt(hex.slice(3,5),16),b=parseInt(hex.slice(5,7),16);return`rgba(${r}, ${g}, ${b}, ${opacity})`}import{useEffect as useEffect12,useState as useState9}from"react";var cached=null,inFlight=null;function fetchChannels(){if(cached)return Promise.resolve(cached);if(inFlight)return inFlight;return inFlight=fetch("/api/plugins/workflows/notification-channels").then((r)=>r.ok?r.json():null).then((data)=>{let list=data&&Array.isArray(data.channels)?data.channels:[];return cached=list,list}).catch(()=>{return cached=[],[]}).finally(()=>{inFlight=null}),inFlight}function useNotificationChannels(){let[channels,setChannels]=useState9(()=>cached??[]);return useEffect12(()=>{if(cached)return;let cancelled=!1;return fetchChannels().then((list)=>{if(!cancelled)setChannels(list)}),()=>{cancelled=!0}},[]),channels}function getChannelLabel(id,channels){return channels.find((c)=>c.id===id)?.label??id}function getChannelInitials(id,channels){let match=channels.find((c)=>c.id===id);if(match?.initials)return match.initials;return id.slice(0,2).toUpperCase()}import{useEffect as useEffect13,useState as useState10}from"react";var cached2=null,inFlight2=null;function fetchAvailableModels(){if(cached2)return Promise.resolve(cached2);if(inFlight2)return inFlight2;return inFlight2=fetch("/api/plugins/models/available").then((r)=>r.ok?r.json():null).then((data)=>{let list=data&&Array.isArray(data.models)?data.models:[];return cached2=list,list}).catch(()=>{return cached2=[],[]}).finally(()=>{inFlight2=null}),inFlight2}function useAvailableModels(){let[models,setModels]=useState10(()=>cached2??[]);return useEffect13(()=>{if(cached2)return;let cancelled=!1;return fetchAvailableModels().then((list)=>{if(!cancelled)setModels(list)}),()=>{cancelled=!0}},[]),models}export{useVerticalResize,useToastStore,useTaskRunHistory,useSidebar,useSearchParams,useSearch,useScheduleJobs,useSSE,useRuntimeStatus,useRunHistory,useRouter,useQueryState,useQueryArrayState,usePluginJsonFetch,usePluginEvent,usePathname,useParams,usePackageState,useOccurrences,useNotificationChannels,useNavBadge,useMainAgentId,useJsonFetch,useHorizontalResize,useHistoryBack,useFormGuard,useFileDrop,useDebug,useContentStore,useAvailableModels,useAgentStore,useAgentList,useAgentIds,useAgentDisplayName,useAgentColor,useAgent,toast,toNavigationOptions,reorderBySearchResults,hexToMuted,getChannelLabel,getChannelInitials,emitPluginEvent};
2
+ var createStoreImpl=(createState)=>{let state,listeners=new Set,setState=(partial,replace)=>{let nextState=typeof partial==="function"?partial(state):partial;if(!Object.is(nextState,state)){let previousState=state;state=(replace!=null?replace:typeof nextState!=="object"||nextState===null)?nextState:Object.assign({},state,nextState),listeners.forEach((listener)=>listener(state,previousState))}},getState=()=>state,api={setState,getState,getInitialState:()=>initialState,subscribe:(listener)=>{return listeners.add(listener),()=>listeners.delete(listener)}},initialState=state=createState(setState,getState,api);return api},createStore=(createState)=>createState?createStoreImpl(createState):createStoreImpl;import React from"react";var identity=(arg)=>arg;function useStore(api,selector=identity){let slice=React.useSyncExternalStore(api.subscribe,React.useCallback(()=>selector(api.getState()),[api,selector]),React.useCallback(()=>selector(api.getInitialState()),[api,selector]));return React.useDebugValue(slice),slice}var createImpl=(createState)=>{let api=createStore(createState),useBoundStore=(selector)=>useStore(api,selector);return Object.assign(useBoundStore,api),useBoundStore},create=(createState)=>createState?createImpl(createState):createImpl;function mapAuditMessage(event,data){switch(event){case"task.dispatched":return`Dispatched: ${data.title}`;case"task.triaged":return`Triaged: ${data.title}`;case"task.created":return`Created task: ${data.title}`;case"task.deleted":return`Deleted task: ${data.title}`;case"task.moved":return`Moved "${data.title}" \u2192 ${data.to}`;case"task.assigned":return`Assigned "${data.title}" to ${data.assignee}`;case"task.blocked":return`Blocked: ${data.title} \u2014 ${data.reason||"no reason"}`;case"task.dispatch_failed":{if(data.category==="model_provider_unavailable")return"Dispatch failed: model provider unavailable";if(typeof data.summary==="string")return data.summary;if(typeof data.error==="string"&&data.error.startsWith("Dispatch failed:"))return data.error;return`Dispatch failed: ${data.error||"unknown error"}`}case"task.updated":return`Updated: ${data.title}`;case"task.routed":{let parts=[data.model,data.thinking?`thinking ${data.thinking}`:null].filter(Boolean),via=typeof data.source==="string"&&data.source!=="inherit"?` via ${data.source==="class"?"class route":String(data.source).replace(/^tag:/,'tag "')+'"'}`:"";return`Routed to ${parts.join(", ")||"override"}${via}`}case"task.completion_suppressed":return`Ignored a duplicate completion${data.title?` of "${data.title}"`:""} \u2014 ${data.firstAgent||"another run"} had already completed this task${data.firstChannel?` via ${data.firstChannel}`:""}.`;case"task.dispatch_failure_ignored":return`A session error arrived after "${data.title||data.id}" had already moved to ${data.column||"done"} \u2014 no action needed.`;case"team.message_blocked":return`Blocked a message to ${data.agentId} \u2014 they are already running task ${data.taskId}.`;case"brand.injected":return`Brand '${data.brandId}' injected into dispatch${data.cardBytes?` (${data.cardBytes} B card)`:""}`;case"brand.dispatch_blocked":return typeof data.message==="string"?data.message:`Task waiting on missing brand '${data.brandId}'`;case"brand.asset_missing":return`Brand '${data.brandId}' has missing asset references`;case"brand.created":return`Created brand '${data.brandId}'`;case"brand.updated":return`Updated brand '${data.brandId}'`;case"brand.deleted":return`Deleted brand '${data.brandId}'`;case"task.worktree_materialized":return`Working in an isolated worktree of ${typeof data.repoPath==="string"?data.repoPath.split("/").pop():"the bound repo"} on branch ${data.branch} \u2014 the branch survives after the task settles`;case"task.turn_aborted":return data.reason==="superseded"?`Stopped a stale attempt on "${data.title||data.id}" \u2014 a fresh attempt takes over`:`Stopped the in-flight attempt on "${data.title||data.id}"${data.reason?` (${data.reason})`:""}`;case"task.turn_force_released":return`Released a hung attempt on task ${data.id} \u2014 its dispatch slot is free again`;case"task.run_superseded":return`Superseded a stalled attempt on "${data.title||data.id}" \u2014 it will be re-dispatched`;case"task.repo_binding_blocked":return typeof data.error==="string"?`Task blocked: ${data.error}`:"Task blocked: repo binding failed";case"dispatch.concurrency_clamped":return`Per-agent parallelism clamped to 1: the active runtime cannot isolate same-agent turns (requested ${data.requested})`;case"asset.stale_run_write_suppressed":return`Recorded a late save from a superseded run as version ${data.version} of ${data.assetId} WITHOUT promoting it \u2014 the current deliverable is unchanged`;case"system.init":return"Bakin started";case"system.dispatch_error":return`Dispatch failed: ${data.error||"unknown error"}`;case"workflow.step_dispatched":return`Step "${data.label||"unknown"}" dispatched to ${data.agent||"agent"}`;case"workflow.step_complete":return`Step "${data.label||"unknown"}" completed`;case"workflow.gate_reached":return`Awaiting approval: ${data.label||"gate"}`;case"workflow.gate_approved":return`Approved: ${data.label||"gate"}`;case"workflow.gate_rejected":return`Rejected: ${data.label||"gate"}${data.reason?` \u2014 ${data.reason}`:""}`;case"workflow.complete":return`Workflow complete${data.workflowId?` (${data.workflowId})`:""}`;default:{if(typeof data.message==="string"&&data.message.trim())return data.message;if(event.startsWith("exec.")){let suffix=event.endsWith(".fail")?" (failed)":event.endsWith(".error")?" (error)":"";if(data.label)return`${data.label}${suffix}`;let toolName=event.replace(/^exec\./,"").replace(/\.(ok|fail|error)$/,"");return humanizeExecName(toolName)+suffix}return event}}}function humanizeExecName(name){let words=name.replace(/^bakin_exec_/,"").split("_");if(words.length===0)return name;return words[0]=words[0].charAt(0).toUpperCase()+words[0].slice(1),words.join(" ")}function isNoisyEvent(evt){if(evt.agent==="system"&&evt.message.startsWith("Dispatch failed"))return!0;if(evt.eventName&&isReadOnlyExecOk(evt.eventName))return!0;if(evt.eventName==="dispatch.registry_clobber")return!0;return!1}function isReadOnlyExecOk(eventName){if(!eventName.startsWith("exec.")||!eventName.endsWith(".ok"))return!1;let toolName=eventName.replace(/^exec\./,"").replace(/\.ok$/,"");if(toolName==="bakin_exec_get_paths"||toolName==="bakin_exec_heartbeat")return!0;return/_(list|get|query|search)$/.test(toolName)}var useContentStore=create((set,get)=>({files:{},heartbeats:{},connected:!1,loading:!0,auditEntries:[],activityEvents:[],sseConnected:!1,debug:!1,setFiles:(files)=>set({files}),updateFile:(key,content)=>set((state)=>({files:{...state.files,[key]:content}})),setHeartbeats:(heartbeats)=>set({heartbeats}),setConnected:(connected)=>set({connected}),appendAuditEntry:(entry)=>set((state)=>({auditEntries:[...state.auditEntries,entry]})),appendActivityEvent:(event)=>set((state)=>{if(isNoisyEvent(event))return state;if(state.activityEvents.some((e)=>e.id===event.id))return state;return{activityEvents:[event,...state.activityEvents].slice(0,100)}}),setActivityEvents:(events)=>set({activityEvents:events.filter((e)=>!isNoisyEvent(e)).slice(0,100)}),setSseConnected:(connected)=>set({sseConnected:connected}),setDebug:(debug)=>{set({debug});try{localStorage.setItem("bakin-debug",String(debug))}catch{}},toggleDebug:()=>{let next=!get().debug;set({debug:next});try{localStorage.setItem("bakin-debug",String(next))}catch{}},initialize:async()=>{try{if(localStorage.getItem("bakin-debug")==="true")set({debug:!0})}catch{}try{let[stateRes,healthRes,activityRes]=await Promise.all([fetch("/api/state"),fetch("/api/agents/health"),fetch("/api/activity")]);if(stateRes.ok){let files=await stateRes.json();set({files})}if(healthRes.ok){let heartbeats=await healthRes.json();set({heartbeats})}if(activityRes.ok){let data=await activityRes.json();if(data?.events)get().setActivityEvents(data.events)}}catch{}finally{set({loading:!1})}}}));import{useEffect}from"react";function buildNavItemsSnapshot(registry){let items=[];for(let[pluginId,navItems]of registry.manifestNavByPlugin.entries()){if(registry.navByPlugin.has(pluginId))continue;items.push(...navItems)}for(let navItems of registry.navByPlugin.values())items.push(...navItems);return items.sort((a,b)=>(a.order??100)-(b.order??100))}function getRegistry(){let g=globalThis;if(!g.__bakinClientRegistry)g.__bakinClientRegistry={navByPlugin:new Map,manifestNavByPlugin:new Map,routesByPlugin:new Map,cleanupByPlugin:new Map,navItemsSnapshot:[],version:0,listeners:new Set,badgesByPlugin:new Map,badgesSnapshot:new Map,badgeListeners:new Set,hitRenderersByPlugin:new Map,hitRenderersSnapshot:new Map,hitRendererListeners:new Set};let registry=g.__bakinClientRegistry;if(!registry.manifestNavByPlugin)registry.manifestNavByPlugin=new Map;if(!Array.isArray(registry.navItemsSnapshot))registry.navItemsSnapshot=buildNavItemsSnapshot(registry);if(!registry.badgesByPlugin)registry.badgesByPlugin=new Map;if(!registry.badgesSnapshot)registry.badgesSnapshot=buildBadgesSnapshot(registry);if(!registry.badgeListeners)registry.badgeListeners=new Set;if(!registry.hitRenderersByPlugin)registry.hitRenderersByPlugin=new Map;if(!registry.hitRenderersSnapshot)registry.hitRenderersSnapshot=buildHitRenderersSnapshot(registry);if(!registry.hitRendererListeners)registry.hitRendererListeners=new Set;return registry}function buildHitRenderersSnapshot(registry){let snapshot=new Map;for(let byType of registry.hitRenderersByPlugin.values())for(let[type,renderer]of byType)if(!snapshot.has(type))snapshot.set(type,renderer);return snapshot}function buildBadgesSnapshot(registry){let snapshot=new Map;for(let byNavItemId of registry.badgesByPlugin.values())for(let[navItemId,badge]of byNavItemId)if(!snapshot.has(navItemId))snapshot.set(navItemId,badge);return snapshot}function bumpBadges(){let registry=getRegistry();registry.badgesSnapshot=buildBadgesSnapshot(registry);for(let l of registry.badgeListeners)try{l()}catch(err){console.error("[bakin] badge listener threw:",err)}}function setNavBadge(pluginId,navItemId,badge){let registry=getRegistry(),plugin=registry.badgesByPlugin.get(pluginId);if(badge===null){if(!plugin?.has(navItemId))return;if(plugin.delete(navItemId),plugin.size===0)registry.badgesByPlugin.delete(pluginId);bumpBadges();return}let prev=plugin?.get(navItemId);if(prev&&prev.count===badge.count&&prev.tone===badge.tone)return;if(!plugin)plugin=new Map,registry.badgesByPlugin.set(pluginId,plugin);plugin.set(navItemId,{count:badge.count,tone:badge.tone}),bumpBadges()}function useNavBadge(pluginId,navItemId,badge){let key=badge?`${badge.count??""}:${badge.tone??""}`:"null";useEffect(()=>{setNavBadge(pluginId,navItemId,badge)},[pluginId,navItemId,key])}function useDebug(){let debug=useContentStore((s)=>s.debug),toggleDebug=useContentStore((s)=>s.toggleDebug);return[debug,toggleDebug]}import{useCallback,useEffect as useEffect2,useRef,useState}from"react";function useJsonFetch(url,opts){let[data,setData]=useState(null),[loading,setLoading]=useState(url!==null),[error,setError]=useState(null),[nonce,setNonce]=useState(0),refresh=useCallback(()=>setNonce((n)=>n+1),[]),optsRef=useRef(opts);return optsRef.current=opts,useEffect2(()=>{if(url===null){setData(null),setLoading(!1),setError(null);return}let controller=new AbortController,{timeoutMs,...init}=optsRef.current??{},timedOut=!1,rejectDeadline=null,deadline=timeoutMs!==void 0&&timeoutMs>0?setTimeout(()=>{timedOut=!0,controller.abort(),rejectDeadline?.(Error("Request timed out"))},timeoutMs):null,clearDeadline=()=>{if(deadline!==null)clearTimeout(deadline);rejectDeadline=null},cancelled=!1;setLoading(!0),setError(null);let request=fetch(url,{...init,signal:controller.signal}).then(async(res)=>{if(!res.ok)throw Error(`Request failed (${res.status})`);return await res.json()});return(deadline===null?request:Promise.race([request,new Promise((_resolve,reject)=>{rejectDeadline=reject})])).then((json)=>{if(clearDeadline(),cancelled)return;if(timedOut){setError("Request timed out"),setLoading(!1);return}setData(json),setLoading(!1)}).catch((err)=>{if(clearDeadline(),cancelled)return;if(timedOut){setError("Request timed out"),setLoading(!1);return}if(err?.name==="AbortError")return;setError(err instanceof Error?err.message:"Request failed"),setLoading(!1)}),()=>{cancelled=!0,clearDeadline(),controller.abort()}},[url,nonce]),{data,loading,error,refresh}}function usePluginJsonFetch(pluginId,path,opts){let clean=path===null?null:path.startsWith("/")?path.slice(1):path;return useJsonFetch(clean===null?null:`/api/plugins/${pluginId}/${clean}`,opts)}import{useState as useState2,useEffect as useEffect3,useCallback as useCallback2}from"react";function useRuntimeStatus(){let[restartNeeded,setRestartNeeded]=useState2(!1),[restarting,setRestarting]=useState2(!1);useEffect3(()=>{fetch("/api/plugins/models/runtime/status").then((r)=>{if(!r.ok)throw Error(`Runtime status: ${r.status}`);return r.json()}).then((data)=>{if(data?.restartNeeded)setRestartNeeded(!0)}).catch((e)=>console.error("Failed to fetch runtime status:",e))},[]);let restart=useCallback2(async()=>{setRestarting(!0);try{if((await fetch("/api/plugins/models/runtime/restart",{method:"POST"})).ok)setRestartNeeded(!1)}finally{setRestarting(!1)}},[]),markDirty=useCallback2(()=>setRestartNeeded(!0),[]);return{restartNeeded,restarting,restart,markDirty}}import{useLocation,useNavigate,useParams as useTanstackParams}from"@tanstack/react-router";import{useMemo}from"react";function toNavigationOptions(url){let hashIndex=url.indexOf("#"),beforeHash=hashIndex>=0?url.slice(0,hashIndex):url,hash=hashIndex>=0?url.slice(hashIndex+1):"",queryIndex=beforeHash.indexOf("?"),to=queryIndex>=0?beforeHash.slice(0,queryIndex):beforeHash,query=queryIndex>=0?beforeHash.slice(queryIndex+1):"",search=Object.create(null);for(let[key,raw]of new URLSearchParams(query))search[key]=raw;return{to,search,hash}}function useRouter(){let navigate=useNavigate();return useMemo(()=>({push:(url,options)=>{navigate({...toNavigationOptions(url),...options?.scroll===!1?{resetScroll:!1}:{}})},replace:(url)=>{navigate({...toNavigationOptions(url),replace:!0,resetScroll:!1})},back:()=>{if(typeof window<"u")window.history.back()},forward:()=>{if(typeof window<"u")window.history.forward()},refresh:()=>{if(typeof window<"u")window.location.reload()},prefetch:()=>{}}),[navigate])}function usePathname(){return useLocation().pathname}function useSearchParams(){let location=useLocation();return useMemo(()=>{let search=location.searchStr;if(typeof search==="string")return new URLSearchParams(search.startsWith("?")?search.slice(1):search);let parsed=location.search;if(parsed&&typeof parsed==="object"){let params=new URLSearchParams;for(let[key,value]of Object.entries(parsed)){if(value===void 0||value===null)continue;params.set(key,String(value))}return params}return new URLSearchParams},[location])}function useParams(){return useTanstackParams({strict:!1})}import{useCallback as useCallback3,useMemo as useMemo2,useRef as useRef2}from"react";var pendingPatch=new Map,pendingPush=!1,pendingNav=null,flushScheduled=!1;function enqueueParamUpdate(key,value,push,router,pathname){if(pendingPatch.set(key,value),pendingPush=pendingPush||push,pendingNav={router,pathname},flushScheduled)return;flushScheduled=!0,queueMicrotask(()=>{let navigation=pendingNav,usePush=pendingPush,patch=new Map(pendingPatch);pendingPatch.clear(),pendingPush=!1,pendingNav=null,flushScheduled=!1;let params=new URLSearchParams(window.location.search);for(let[patchKey,patchValue]of patch)if(patchValue===null)params.delete(patchKey);else params.set(patchKey,patchValue);let query=params.toString(),url=query?`${navigation.pathname}?${query}`:navigation.pathname;if(usePush)navigation.router.push(url,{scroll:!1});else navigation.router.replace(url,{scroll:!1})})}function useQueryState(key,defaultValue=""){let searchParams=useSearchParams(),router=useRouter(),pathname=usePathname(),pathnameRef=useRef2(pathname);pathnameRef.current=pathname;let value=searchParams.get(key)??defaultValue,setValue=useCallback3((next)=>{enqueueParamUpdate(key,next===defaultValue?null:next,!1,router,pathnameRef.current)},[key,defaultValue,router]),pushValue=useCallback3((next)=>{enqueueParamUpdate(key,next===defaultValue?null:next,!0,router,pathnameRef.current)},[key,defaultValue,router]);return[value,setValue,pushValue]}function useQueryArrayState(key){let searchParams=useSearchParams(),router=useRouter(),pathname=usePathname(),pathnameRef=useRef2(pathname);pathnameRef.current=pathname;let value=useMemo2(()=>{let raw=searchParams.get(key);return raw?raw.split(",").filter(Boolean):[]},[searchParams,key]),setValue=useCallback3((next)=>{enqueueParamUpdate(key,next.length===0?null:next.join(","),!1,router,pathnameRef.current)},[key,router]);return[value,setValue]}import{useNavigate as useNavigate2,useRouter as useTanStackRouter}from"@tanstack/react-router";import{useCallback as useCallback4}from"react";function useHistoryBack(fallbackTo){let router=useTanStackRouter(),navigate=useNavigate2();return useCallback4(()=>{if(router.history.canGoBack())router.history.back();else navigate({to:fallbackTo})},[router,navigate,fallbackTo])}import{useState as useState3,useEffect as useEffect4,useCallback as useCallback5,useRef as useRef3}from"react";function useScheduleJobs(options={}){let[jobs,setJobs]=useState3([]),[loading,setLoading]=useState3(!0),[fetchFailed,setFetchFailed]=useState3(!1),optionsRef=useRef3(options);optionsRef.current=options;let fetchJobs=useCallback5(async()=>{try{let res=await fetch("/api/plugins/schedule/");if(res.ok){let data=await res.json();setJobs(data.jobs||[]),setFetchFailed(!1)}else setFetchFailed(!0)}catch{setFetchFailed(!0)}finally{setLoading(!1)}},[]);useEffect4(()=>{fetchJobs()},[fetchJobs]),useEffect4(()=>{let es=new EventSource("/api/events"),handler=(event)=>{try{let data=JSON.parse(event.data);if(data.type==="activity"&&data.message?.includes("Schedule")||data.event?.startsWith("schedule."))fetchJobs()}catch{}};return es.addEventListener("message",handler),()=>{es.removeEventListener("message",handler),es.close()}},[fetchJobs]);let opts=options,filtered=jobs.filter((j)=>{if(opts.agent&&j.agentId!==opts.agent)return!1;return!0}),pauseJob=useCallback5(async(jobId,pauseUntil)=>{try{let res=await fetch(`/api/plugins/schedule/${jobId}/pause`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:"pause",pauseUntil})});if(res.ok)fetchJobs();return res.ok}catch{return!1}},[fetchJobs]),resumeJob=useCallback5(async(jobId)=>{try{let res=await fetch(`/api/plugins/schedule/${jobId}/pause`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:"resume"})});if(res.ok)fetchJobs();return res.ok}catch{return!1}},[fetchJobs]),deleteJob=useCallback5(async(jobId)=>{try{let res=await fetch(`/api/plugins/schedule/${jobId}`,{method:"DELETE",headers:{"Content-Type":"application/json"}});if(res.ok)setJobs((prev)=>prev.filter((j)=>j.id!==jobId));return res.ok}catch{return!1}},[]),runNow=useCallback5(async(jobId)=>{try{return(await fetch(`/api/plugins/schedule/${jobId}/run`,{method:"POST",headers:{"Content-Type":"application/json"}})).ok}catch{return!1}},[]),updateJob=useCallback5(async(jobId,data)=>{try{let res=await fetch(`/api/plugins/schedule/${jobId}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(data)});if(res.ok)fetchJobs();return res.ok}catch{return!1}},[fetchJobs]),adoptJob=useCallback5(async(jobId,data)=>{try{let res=await fetch(`/api/plugins/schedule/${jobId}/adopt`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(data)});if(res.ok)fetchJobs();return res.ok}catch{return!1}},[fetchJobs]),restoreNative=useCallback5(async(jobId)=>{try{let res=await fetch(`/api/plugins/schedule/${jobId}/restore-native`,{method:"POST",headers:{"Content-Type":"application/json"}});if(res.ok)fetchJobs();return res.ok}catch{return!1}},[fetchJobs]),skipNext=useCallback5(async(jobId,n=1)=>{try{let res=await fetch(`/api/plugins/schedule/${jobId}/pause`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:"skip",skipN:n})});if(res.ok)fetchJobs();return res.ok}catch{return!1}},[fetchJobs]),duplicateJob=useCallback5(async(jobId,overrides={})=>{let source=jobs.find((j)=>j.id===jobId);if(!source)return!1;try{let res=await fetch("/api/plugins/schedule/",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:overrides.name??`${source.displayName} (copy)`,schedule:overrides.schedule??source.humanSchedule,agentId:overrides.agentId??source.agentId,teamId:overrides.teamId??source.teamId,taskPrompt:overrides.taskPrompt??source.taskPrompt,taskTitle:overrides.taskTitle??source.taskTitle,workflowId:overrides.workflowId??source.workflowId,owner:overrides.owner??source.owner,requireTriage:overrides.requireTriage??source.requireTriage,allowOverlap:overrides.allowOverlap??source.allowOverlap,maxFailures:overrides.maxFailures??source.maxFailures,...overrides})});if(res.ok)fetchJobs();return res.ok}catch{return!1}},[jobs,fetchJobs]);return{jobs:filtered,allJobs:jobs,loading,fetchFailed,refresh:fetchJobs,pauseJob,resumeJob,deleteJob,runNow,updateJob,adoptJob,restoreNative,skipNext,duplicateJob}}function useOccurrences(fromIso,toIso){let[occurrences,setOccurrences]=useState3([]),[events,setEvents]=useState3([]),[unevaluated,setUnevaluated]=useState3([]),[droppedProviders,setDroppedProviders]=useState3([]),[loading,setLoading]=useState3(!0),fetchOccurrences=useCallback5(async()=>{try{let res=await fetch(`/api/plugins/schedule/occurrences?from=${encodeURIComponent(fromIso)}&to=${encodeURIComponent(toIso)}`);if(res.ok){let data=await res.json();setOccurrences(data.occurrences||[]),setEvents(data.events||[]),setUnevaluated(data.unevaluated||[]),setDroppedProviders(data.droppedProviders||[])}}catch{}finally{setLoading(!1)}},[fromIso,toIso]);return useEffect4(()=>{fetchOccurrences()},[fetchOccurrences]),useEffect4(()=>{let es=new EventSource("/api/events"),handler=(event)=>{try{let data=JSON.parse(event.data);if(data.type==="activity"&&data.message?.includes("Schedule")||data.event?.startsWith("schedule.")||data.type==="taskboard"||data.event?.endsWith(".scheduled_events_changed"))fetchOccurrences()}catch{}};return es.addEventListener("message",handler),()=>{es.removeEventListener("message",handler),es.close()}},[fetchOccurrences]),{occurrences,events,unevaluated,droppedProviders,loading,refresh:fetchOccurrences}}function useRunHistory(jobId,limit=20){let[runs,setRuns]=useState3([]),[loading,setLoading]=useState3(!1);return useEffect4(()=>{if(!jobId){setRuns([]);return}setLoading(!0),fetch(`/api/plugins/schedule/${jobId}/runs?limit=${limit}`).then((res)=>res.ok?res.json():null).then((data)=>{if(data)setRuns(data.runs||[])}).catch(()=>{}).finally(()=>setLoading(!1))},[jobId,limit]),{runs,loading}}import{useState as useState4,useEffect as useEffect5}from"react";function useTaskRunHistory(taskId,limit=50){let[runs,setRuns]=useState4([]),[outcome,setOutcome]=useState4(void 0),[loading,setLoading]=useState4(!1);return useEffect5(()=>{if(setRuns([]),setOutcome(void 0),!taskId)return;let controller=new AbortController;return setLoading(!0),fetch(`/api/plugins/tasks/${taskId}/runs?limit=${limit}`,{signal:controller.signal}).then((res)=>res.ok?res.json():null).then((data)=>{if(data)setRuns(data.runs||[]),setOutcome(data.outcome)}).catch(()=>{}).finally(()=>{if(!controller.signal.aborted)setLoading(!1)}),()=>controller.abort()},[taskId,limit]),{runs,outcome,loading}}import{useState as useState5,useEffect as useEffect6,useCallback as useCallback6,useRef as useRef4}from"react";function reorderBySearchResults(items,searchResults){if(!searchResults.length)return items;let scoreMap=new Map;for(let r of searchResults)scoreMap.set(r.id,r.score);let matched=[],unmatched=[];for(let item of items)if(scoreMap.has(item.id))matched.push(item);else unmatched.push(item);return matched.sort((a,b)=>(scoreMap.get(b.id)??0)-(scoreMap.get(a.id)??0)),[...matched,...unmatched]}function useSearch(options={}){let{plugin,limit=20,facets,types,debounce:debounceMs=250}=options,[results,setResults]=useState5([]),[aggregations,setAggregations]=useState5({}),[status,setStatus]=useState5("idle"),[error,setError]=useState5(null),[meta,setMeta]=useState5(null),abortRef=useRef4(null),timerRef=useRef4(null),mountedRef=useRef4(!0),lastQueryRef=useRef4(""),typesKey=types?.join(",");useEffect6(()=>{return mountedRef.current=!0,()=>{if(mountedRef.current=!1,abortRef.current?.abort(),timerRef.current)clearTimeout(timerRef.current)}},[]);let executeSearch=useCallback6(async(q)=>{if(!q.trim()){setResults([]),setAggregations({}),setMeta(null),setError(null),setStatus("idle");return}abortRef.current?.abort();let controller=new AbortController;abortRef.current=controller,setStatus("loading"),setError(null);try{let params=new URLSearchParams({q});if(limit)params.set("limit",String(limit));if(facets?.length)params.set("facets",facets.join(","));if(typesKey)params.set("types",typesKey);let url=plugin?`/api/plugins/${plugin}/search?${params}`:`/api/search?${params}`,res=await fetch(url,{signal:AbortSignal.any([controller.signal,AbortSignal.timeout(15000)])});if(!mountedRef.current)return;if(res.status===503){setResults([]),setAggregations({}),setMeta(null),setStatus("unavailable");return}if(!res.ok)throw Error(`Search failed: ${res.status}`);let data=await res.json();if(!mountedRef.current)return;setResults(Array.isArray(data.results)?data.results:[]),setAggregations(data.aggregations||{}),setMeta(data.meta||null),setStatus("ok")}catch(err){if(!mountedRef.current)return;if(err instanceof DOMException&&err.name==="AbortError")return;let msg=err instanceof Error?err.message:String(err);setError(msg),setResults([]),setAggregations({}),setStatus("error")}},[plugin,limit,facets,typesKey]),search=useCallback6((q)=>{if(lastQueryRef.current=q,timerRef.current)clearTimeout(timerRef.current);if(!q.trim()){setResults([]),setAggregations({}),setMeta(null),setError(null),setStatus("idle");return}setStatus("loading"),timerRef.current=setTimeout(()=>executeSearch(q),debounceMs)},[executeSearch,debounceMs]),retry=useCallback6(()=>{if(lastQueryRef.current.trim())executeSearch(lastQueryRef.current)},[executeSearch]),clear=useCallback6(()=>{if(lastQueryRef.current="",setResults([]),setAggregations({}),setMeta(null),setError(null),setStatus("idle"),abortRef.current?.abort(),timerRef.current)clearTimeout(timerRef.current)},[]);return{results,aggregations,status,loading:status==="loading",error,meta,search,clear,retry}}import{useState as useState6,useEffect as useEffect7}from"react";function useSidebar(){let[collapsed,setCollapsed]=useState6(!1);return useEffect7(()=>{if(localStorage.getItem("sidebar-collapsed")==="true")setCollapsed(!0)},[]),{collapsed,toggle:()=>setCollapsed((c)=>{return localStorage.setItem("sidebar-collapsed",String(!c)),!c})}}import{useEffect as useEffect9,useRef as useRef6}from"react";import{useEffect as useEffect8,useRef as useRef5}from"react";var subscribers=globalThis.__bakinPluginEventSubs??(globalThis.__bakinPluginEventSubs=new Map);function emitPluginEvent(payload){let event=payload?.event;if(typeof event!=="string")return;let set=subscribers.get(event);if(!set)return;for(let handler of[...set])try{handler(payload)}catch{}}function usePluginEvent(event,handler){let handlerRef=useRef5(handler);handlerRef.current=handler,useEffect8(()=>{let wrapped=(payload)=>handlerRef.current(payload),set=subscribers.get(event);if(!set)set=new Set,subscribers.set(event,set);return set.add(wrapped),()=>{if(set.delete(wrapped),set.size===0)subscribers.delete(event)}},[event])}function navigateToUrl(url){let bridge=globalThis.__bakinNavigate;if(bridge){bridge(url);return}window.location.assign(url)}function isNotificationsSupported(){return typeof window<"u"&&"Notification"in window&&window.isSecureContext}function isNotificationsEnabled(){if(!isNotificationsSupported())return!1;return localStorage.getItem("bakin-notifications-enabled")==="true"&&Notification.permission==="granted"}function sendBrowserNotification(title,body,url){if(!isNotificationsEnabled())return;if(document.hasFocus())return;let notification=new Notification(title,{body,icon:"/favicon.ico"});if(url)notification.onclick=()=>{window.focus(),navigateToUrl(url),notification.close()}}var MAX_RETRIES=20,BASE_DELAY=1000,MAX_DELAY=30000;function isDevPluginHotReloadActive(){return typeof document<"u"&&!!document.querySelector('script[src="/__bakin-dev/client.js"]')}function useSSE(){let updateFile=useContentStore((s)=>s.updateFile),setConnected=useContentStore((s)=>s.setConnected),setHeartbeats=useContentStore((s)=>s.setHeartbeats),initialize=useContentStore((s)=>s.initialize),appendAuditEntry=useContentStore((s)=>s.appendAuditEntry),appendActivityEvent=useContentStore((s)=>s.appendActivityEvent),setSseConnected=useContentStore((s)=>s.setSseConnected),esRef=useRef6(null),retryRef=useRef6(0),timeoutRef=useRef6(null),hbTimerRef=useRef6(null);useEffect9(()=>{initialize();function connect(){if(esRef.current)esRef.current.close(),esRef.current=null;let es=new EventSource("/api/events");esRef.current=es,es.onopen=()=>{setConnected(!0),setSseConnected(!0),retryRef.current=0},es.onmessage=(e)=>{try{let data=JSON.parse(e.data);if(data.type==="plugin-event")emitPluginEvent(data);if(data.type==="taskboard"){emitPluginEvent({event:"taskboard"});return}if(data.type==="turn-activity"){emitPluginEvent({...data,event:"turn-activity"});return}if(data.type==="plugin:manifest-changed"){if(!isDevPluginHotReloadActive())window.location.reload();return}if(data.type==="activity"){appendActivityEvent({id:`${data.ts}-activity-${data.agent}`,ts:data.ts,type:"log",agent:data.agent||"system",message:data.message,taskId:data.taskId});return}if(data.type==="audit"&&data.entry){let entry=data.entry,entryData=entry.data||{};if(appendAuditEntry(entry),entry.event==="doctor.run")emitPluginEvent({event:"doctor.run"});appendActivityEvent({id:`${entry.ts}-${entry.event}-${entry.agent}`,ts:entry.ts,type:"audit",agent:entry.agent||"system",message:mapAuditMessage(entry.event,entryData),taskId:entryData.taskId,taskTitle:entryData.title,eventName:entry.event,...entryData.duplicate?{duplicate:!0}:{},data:entryData})}if(data.type==="plugin-event"&&typeof data.event==="string"&&data.event.startsWith("workflow.")){if(data.event.startsWith("workflow.gate")||data.event==="workflow.complete")initialize();if(data.event==="workflow.gate_reached")sendBrowserNotification("Approval needed",data.label||"A workflow gate needs your review");appendAuditEntry({ts:data.timestamp||new Date().toISOString(),event:data.event,agent:"workflow",data:{taskId:data.taskId,label:data.label,agent:data.agent,reason:data.reason,workflowId:data.workflowId}}),appendActivityEvent({id:`${data.timestamp||new Date().toISOString()}-${data.event}-workflow`,ts:data.timestamp||new Date().toISOString(),type:"audit",agent:"workflow",message:mapAuditMessage(data.event,data),taskId:data.taskId,eventName:data.event})}if(data.type==="plugin-event"&&data.event==="budget.incident_opened")sendBrowserNotification("Budget alert",data.message||"A budget cap was reached \u2014 dispatch may be deferred","/models?tab=spend"),appendActivityEvent({id:`${data.timestamp||new Date().toISOString()}-budget-incident-${data.incidentId}`,ts:data.timestamp||new Date().toISOString(),type:"alert",agent:"system",message:data.message||"Budget incident opened",eventName:"budget.incident_opened",data:{incidentId:data.incidentId,scope:data.scope,scopeId:data.scopeId,lane:data.lane,window:data.window}});if(data.type==="plugin-event"&&data.event==="brand.dispatch_blocked")sendBrowserNotification("Brand unavailable",data.message||`A task is waiting on brand '${data.brandId}'`,`/tasks?brand=${encodeURIComponent(data.brandId||"")}`),appendActivityEvent({id:`${data.timestamp||new Date().toISOString()}-brand-blocked-${data.taskId}`,ts:data.timestamp||new Date().toISOString(),type:"alert",agent:"system",message:data.message||"Task blocked on a missing brand",eventName:"brand.dispatch_blocked",data:{taskId:data.taskId,brandId:data.brandId}});if(data.type==="alert")appendActivityEvent({id:`${data.timestamp||new Date().toISOString()}-alert-system`,ts:data.timestamp||new Date().toISOString(),type:"alert",agent:"system",message:data.message||"Watchdog alert"});if(data.type==="search.rebuild.start")emitPluginEvent({event:"search.rebuild.start",table:data.table});if(data.type==="search.rebuild.progress")emitPluginEvent({event:"search.rebuild.progress",table:data.table,indexed:data.indexed??0});if(data.type==="search.rebuild.complete")emitPluginEvent({event:"search.rebuild.complete",table:data.table,indexed:data.indexed??0});if(data.type==="reindex.batch_start")appendActivityEvent({id:`${Date.now()}-reindex-batch-start`,ts:new Date().toISOString(),type:"log",agent:"system",message:`Starting full re-index (${data.tables} table${data.tables===1?"":"s"})`});if(data.type==="reindex.batch_pulse"){let pct=data.tables_total?Math.floor(data.tables_done/data.tables_total*100):0;appendActivityEvent({id:`${Date.now()}-reindex-batch-pulse`,ts:new Date().toISOString(),type:"log",agent:"system",message:`Re-indexing\u2026 ${data.tables_done}/${data.tables_total} tables (${pct}%), ${data.indexed} documents so far`})}if(data.type==="reindex.batch_complete"){let seconds=Math.max(1,Math.round((data.elapsed_ms??0)/1000));appendActivityEvent({id:`${Date.now()}-reindex-batch-complete`,ts:new Date().toISOString(),type:"log",agent:"system",message:`Completed full re-index \u2014 ${data.indexed} documents across ${data.tables} table${data.tables===1?"":"s"} in ${seconds}s`})}if(data.file&&data.content!==void 0){if(updateFile(data.file,data.content),data.file.startsWith("heartbeats/")&&data.file.endsWith(".json")){if(hbTimerRef.current)clearTimeout(hbTimerRef.current);hbTimerRef.current=setTimeout(()=>{fetch("/api/agents/health").then((r)=>r.ok?r.json():null).then((hb)=>{if(hb)setHeartbeats(hb)}).catch(()=>{})},500)}}}catch{}},es.onerror=()=>{if(setConnected(!1),setSseConnected(!1),es.close(),esRef.current=null,retryRef.current<MAX_RETRIES){let delay=Math.min(BASE_DELAY*Math.pow(2,retryRef.current),MAX_DELAY);retryRef.current++,timeoutRef.current=setTimeout(connect,delay)}}}return connect(),()=>{if(timeoutRef.current)clearTimeout(timeoutRef.current);if(hbTimerRef.current)clearTimeout(hbTimerRef.current);esRef.current?.close(),esRef.current=null}},[updateFile,setConnected,setHeartbeats,initialize,appendAuditEntry,appendActivityEvent,setSseConnected])}var DEFAULT_DURATION={success:4000,info:4000,error:1e4},counter=0,useToastStore=create((set)=>({toasts:[],add:(toast)=>{let id=String(++counter);return set((s)=>({toasts:[...s.toasts,{...toast,id}]})),setTimeout(()=>{set((s)=>({toasts:s.toasts.filter((t)=>t.id!==id)}))},toast.duration??DEFAULT_DURATION[toast.type]),id},dismiss:(id)=>set((s)=>({toasts:s.toasts.filter((t)=>t.id!==id)}))}));function toast(message,type="info",duration){return useToastStore.getState().add({message,type,...duration?{duration}:{}})}import{useCallback as useCallback7,useEffect as useEffect10,useRef as useRef7,useState as useState7}from"react";var KEY_STEP=16,KEY_STEP_LARGE=64;function clamp(n,min,max){return Math.min(max,Math.max(min,n))}function readStored(def,min,max,prefix,storageKey){if(!storageKey||typeof window>"u")return clamp(def,min,max);try{let raw=window.localStorage.getItem(prefix+storageKey);if(!raw)return clamp(def,min,max);let parsed=Number.parseInt(raw,10);return Number.isFinite(parsed)?clamp(parsed,min,max):clamp(def,min,max)}catch(err){return console.error("useResizablePane: failed to read stored size",err),clamp(def,min,max)}}function useResizablePane({axis,defaultSize,minSize,maxSize,storageKey,storagePrefix}){let[size,setSizeState]=useState7(()=>readStored(defaultSize,minSize,maxSize,storagePrefix,storageKey)),sizeRef=useRef7(size),dragging=useRef7(!1),dragStart=useRef7(0),dragStartSize=useRef7(0),persist=useCallback7((n)=>{if(!storageKey||typeof window>"u")return;try{window.localStorage.setItem(storagePrefix+storageKey,String(clamp(n,minSize,maxSize)))}catch(err){console.error("useResizablePane: failed to persist size",err)}},[storageKey,storagePrefix,minSize,maxSize]),setSize=useCallback7((n)=>{let next=clamp(n,minSize,maxSize);sizeRef.current=next,setSizeState(next),persist(next)},[minSize,maxSize,persist]);useEffect10(()=>{let clamped=clamp(sizeRef.current,minSize,maxSize);if(clamped!==sizeRef.current)setSize(clamped)},[minSize,maxSize,setSize]);let beginDrag=useCallback7((client)=>{dragging.current=!0,dragStart.current=client,dragStartSize.current=sizeRef.current},[]),onMove=useCallback7((client)=>{if(!dragging.current)return;let delta=dragStart.current-client,next=clamp(dragStartSize.current+delta,minSize,maxSize);sizeRef.current=next,setSizeState(next)},[minSize,maxSize]),endDrag=useCallback7(()=>{if(!dragging.current)return;dragging.current=!1,persist(sizeRef.current),document.body.style.cursor="",document.body.style.userSelect=""},[persist]),onMouseDown=useCallback7((e)=>{e.preventDefault(),beginDrag(axis==="x"?e.clientX:e.clientY);let move=(ev)=>onMove(axis==="x"?ev.clientX:ev.clientY),up=()=>{document.removeEventListener("mousemove",move),document.removeEventListener("mouseup",up),endDrag()};document.addEventListener("mousemove",move),document.addEventListener("mouseup",up),document.body.style.cursor=axis==="x"?"col-resize":"row-resize",document.body.style.userSelect="none"},[axis,beginDrag,onMove,endDrag]),onTouchStart=useCallback7((e)=>{let touch=e.touches[0];if(!touch)return;beginDrag(axis==="x"?touch.clientX:touch.clientY);let move=(ev)=>{let t=ev.touches[0];if(!t)return;ev.preventDefault(),onMove(axis==="x"?t.clientX:t.clientY)},up=()=>{document.removeEventListener("touchmove",move),document.removeEventListener("touchend",up),document.removeEventListener("touchcancel",up),endDrag()};document.addEventListener("touchmove",move,{passive:!1}),document.addEventListener("touchend",up),document.addEventListener("touchcancel",up)},[axis,beginDrag,onMove,endDrag]),onKeyDown=useCallback7((e)=>{let growKey=axis==="x"?"ArrowLeft":"ArrowUp",shrinkKey=axis==="x"?"ArrowRight":"ArrowDown",dir=0;if(e.key===growKey)dir=1;else if(e.key===shrinkKey)dir=-1;else return;e.preventDefault();let step=e.shiftKey?KEY_STEP_LARGE:KEY_STEP;setSize(sizeRef.current+dir*step)},[axis,setSize]);return{size,setSize,handleProps:{role:"separator",tabIndex:0,"aria-orientation":axis==="x"?"vertical":"horizontal","aria-valuenow":size,"aria-valuemin":minSize,"aria-valuemax":maxSize,onMouseDown,onTouchStart,onKeyDown}}}function useHorizontalResize({defaultWidth,minWidth,maxWidth,storageKey}){let{size,setSize,handleProps}=useResizablePane({axis:"x",defaultSize:defaultWidth,minSize:minWidth,maxSize:maxWidth,storageKey,storagePrefix:"bakin-hresize:"});return{width:size,setWidth:setSize,handleProps}}async function parsePackageStatesResponse(res){if(!res||!res.ok)return{};try{let body=await res.json();if(!body.ok||!Array.isArray(body.agents))return{};let map={};for(let row of body.agents)map[row.agentId]=row;return map}catch{return{}}}var ROSTER_CACHE_KEY="bakin-agent-roster-v1";function readRosterCache(){try{if(typeof window>"u")return null;let raw=window.localStorage.getItem(ROSTER_CACHE_KEY);if(!raw)return null;let parsed=JSON.parse(raw);if(!Array.isArray(parsed.agents))return null;return{agents:parsed.agents.filter((a)=>!!a&&typeof a==="object"&&typeof a.id==="string"&&typeof a.name==="string"),displaySettings:parsed.displaySettings&&typeof parsed.displaySettings==="object"?parsed.displaySettings:{},mainAgentId:typeof parsed.mainAgentId==="string"?parsed.mainAgentId:null}}catch{return null}}function writeRosterCache(cache){try{window.localStorage.setItem(ROSTER_CACHE_KEY,JSON.stringify(cache))}catch{}}var hydrated=readRosterCache(),hydratedMap={};for(let a of hydrated?.agents??[])hydratedMap[a.id]=a;var useAgentStore=create((set,get)=>({agents:hydrated?.agents??[],agentIds:(hydrated?.agents??[]).map((a)=>a.id),agentMap:hydratedMap,agentsWithStatus:[],displaySettings:hydrated?.displaySettings??{},teams:[],packageStates:{},mainAgentId:hydrated?.mainAgentId??null,loaded:!1,load:async()=>{try{let[rosterRes,pkgRes]=await Promise.all([fetch("/api/plugins/team/"),fetch("/api/agent-packages?check=1").catch(()=>null)]);if(!rosterRes.ok){set({loaded:!0});return}let data=await rosterRes.json(),agents=data.agents.map(({status:_status,heartbeat:_heartbeat,heartbeatAge:_heartbeatAge,model:_model,...meta})=>meta),agentMap={};for(let a of agents)agentMap[a.id]=a;let packageStates=await parsePackageStatesResponse(pkgRes);set({agents,agentIds:agents.map((a)=>a.id),agentMap,agentsWithStatus:data.agents,displaySettings:data.displaySettings,teams:data.teams??[],packageStates,mainAgentId:data.mainAgentId??null,loaded:!0}),writeRosterCache({agents,displaySettings:data.displaySettings,mainAgentId:data.mainAgentId??null})}catch{set({loaded:!0})}},refreshPackageStates:async()=>{let res=await fetch("/api/agent-packages?check=1").catch(()=>null),packageStates=await parsePackageStatesResponse(res);set({packageStates})},updateDisplay:async(agentId,patch)=>{let current=get().displaySettings,updated={...current,[agentId]:{...current[agentId],...patch}};set({displaySettings:updated}),await fetch("/api/plugins/team/settings",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(updated)})}}));function useAgent(agentId){return useAgentStore((s)=>s.agentMap[agentId])}function useAgentList(){return useAgentStore((s)=>s.agents)}function useAgentColor(agentId){return useAgentStore((s)=>s.displaySettings[agentId]?.accentColor??"#a1a1aa")}function usePackageState(agentId){return useAgentStore((s)=>s.packageStates?.[agentId])}function useAgentDisplayName(agentId){return useAgentStore((s)=>s.displaySettings[agentId]?.displayName)}function useAgentIds(){return useAgentStore((s)=>s.agentIds)}function useMainAgentId(){return useAgentStore((s)=>s.mainAgentId)}function hexToMuted(hex,opacity=0.2){let r=parseInt(hex.slice(1,3),16),g=parseInt(hex.slice(3,5),16),b=parseInt(hex.slice(5,7),16);return`rgba(${r}, ${g}, ${b}, ${opacity})`}import{useEffect as useEffect11,useState as useState8}from"react";var cached=null,inFlight=null;function fetchChannels(){if(cached)return Promise.resolve(cached);if(inFlight)return inFlight;return inFlight=fetch("/api/plugins/workflows/notification-channels").then((r)=>r.ok?r.json():null).then((data)=>{let list=data&&Array.isArray(data.channels)?data.channels:[];return cached=list,list}).catch(()=>{return cached=[],[]}).finally(()=>{inFlight=null}),inFlight}function useNotificationChannels(){let[channels,setChannels]=useState8(()=>cached??[]);return useEffect11(()=>{if(cached)return;let cancelled=!1;return fetchChannels().then((list)=>{if(!cancelled)setChannels(list)}),()=>{cancelled=!0}},[]),channels}function getChannelLabel(id,channels){return channels.find((c)=>c.id===id)?.label??id}function getChannelInitials(id,channels){let match=channels.find((c)=>c.id===id);if(match?.initials)return match.initials;return id.slice(0,2).toUpperCase()}import{useEffect as useEffect12,useState as useState9}from"react";var cached2=null,inFlight2=null;function fetchAvailableModels(){if(cached2)return Promise.resolve(cached2);if(inFlight2)return inFlight2;return inFlight2=fetch("/api/plugins/models/available").then((r)=>r.ok?r.json():null).then((data)=>{let list=data&&Array.isArray(data.models)?data.models:[];return cached2=list,list}).catch(()=>{return cached2=[],[]}).finally(()=>{inFlight2=null}),inFlight2}function useAvailableModels(){let[models,setModels]=useState9(()=>cached2??[]);return useEffect12(()=>{if(cached2)return;let cancelled=!1;return fetchAvailableModels().then((list)=>{if(!cancelled)setModels(list)}),()=>{cancelled=!0}},[]),models}export{useToastStore,useTaskRunHistory,useSidebar,useSearchParams,useSearch,useScheduleJobs,useSSE,useRuntimeStatus,useRunHistory,useRouter,useQueryState,useQueryArrayState,usePluginJsonFetch,usePluginEvent,usePathname,useParams,usePackageState,useOccurrences,useNotificationChannels,useNavBadge,useMainAgentId,useJsonFetch,useHorizontalResize,useHistoryBack,useDebug,useContentStore,useAvailableModels,useAgentStore,useAgentList,useAgentIds,useAgentDisplayName,useAgentColor,useAgent,toast,toNavigationOptions,reorderBySearchResults,hexToMuted,getChannelLabel,getChannelInitials,emitPluginEvent};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@makinbakin/sdk",
3
- "version": "0.0.1-rc.28",
3
+ "version": "0.0.1-rc.29",
4
4
  "description": "SDK for building Bakin plugins — UI components, slot types, hooks, and the runtime registerPlugin helper.",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -4,7 +4,7 @@
4
4
  * Recipes own page hierarchy, responsive composition, and state slots while
5
5
  * consumers retain domain data, URL state, and routing behavior.
6
6
  */
7
- export { InspectorPanel, InspectorPanelContent, InspectorPanelFooter, InspectorPanelHeader, KanbanBoard, KanbanCardSignal, KanbanColumn, KanbanColumnBody, KanbanColumnEmpty, KanbanColumnHeader, CalendarGrid, CalendarItem, CalendarNav, ListRow, ListRowActions, ListRowGroup, ListRowLabels, ListRows, NavList, NodeCard, Page, PageAside, useCollapsedAside, PageBody, PageCanvas, PageComposer, PageControls, PageTimeline, Pagination, PageHeader, PageHeaderOverflowMenu, WorkspacePage, WorkspacePageBody, WorkspacePageCompactHeader, WorkspacePageHeader, WorkspacePageMetrics, ConfirmDialog, CopyButton, KeyValue, DangerZone, DataTable, FacetFilter, AgentFilter, SaveBar, SearchInput, SegmentedControl, SortableHead, StatGroup, StatTile, StatusBadge, StatusMarker, Timeline, TimelineEntry, UnsavedChangesDialog, } from '../_internal/ui/patterns';
7
+ export { InspectorPanel, InspectorPanelContent, InspectorPanelFooter, InspectorPanelHeader, KanbanBoard, KanbanCardSignal, KanbanColumn, KanbanColumnBody, KanbanColumnEmpty, KanbanColumnHeader, CalendarGrid, CalendarItem, CalendarNav, ListRow, ListRowActions, ListRowGroup, ListRowLabels, ListRows, NavList, NodeCard, Page, PageAside, useCollapsedAside, PageBody, PageCanvas, PageComposer, PageControls, PageTimeline, Pagination, PageHeader, WorkspacePage, WorkspacePageBody, WorkspacePageCompactHeader, WorkspacePageHeader, WorkspacePageMetrics, ConfirmDialog, CopyButton, KeyValue, DangerZone, DataTable, FacetFilter, AgentFilter, SaveBar, SearchInput, SegmentedControl, SortableHead, StatGroup, StatTile, StatusBadge, StatusMarker, Timeline, TimelineEntry, UnsavedChangesDialog, } from '../_internal/ui/patterns';
8
8
  /** Replace an affected result region when search returns no trustworthy result. */
9
9
  export { SearchUnavailable } from './search-patterns';
10
10
  /** Show fused and per-leg search relevance as exact, non-color-dependent evidence. */
@@ -19,7 +19,7 @@ export type { ScoreOverlayInfo, ScoreOverlayProps, SearchDegradedChipProps, Sear
19
19
  /** Present agent identity without importing a registry or host store. */
20
20
  export { AgentAvatar, AgentDot, AgentStatus, AgentSelect } from './agent-patterns';
21
21
  /** Stable assignment-value helpers shared by forms and workflow configuration. */
22
- export { ASSIGNED_AGENT_VALUE, TEAM_VALUE_PREFIX, isTeamValue, teamIdFromValue, } from './agent-patterns';
22
+ export { TEAM_VALUE_PREFIX, isTeamValue, teamIdFromValue, } from './agent-patterns';
23
23
  export type { AgentAvatarProps, AgentDotProps, AgentIdentity, AgentPresenceStatus, AgentSelectOption, AgentSelectProps, AgentStatusProps, AgentTeamOption, } from './agent-patterns';
24
24
  /** Controlled asset, model, and color choices without app data ownership. */
25
25
  export { AssetPicker, ColorPicker, DEFAULT_MODEL_VALUE, ModelSelect } from './picker-patterns';
@@ -37,4 +37,4 @@ export type { ChannelIconChannel, ChannelIconProps, ChannelIconSize } from './ch
37
37
  export { PluginSettingsRenderer } from './plugin-settings-renderer';
38
38
  export type { PluginSettingsFeedback, PluginSettingsRendererProps, } from './plugin-settings-renderer';
39
39
  export type { BooleanSettingsField, ListSettingsField, NumberSettingsField, PluginSettingsSchema, SelectSettingsField, SettingsField, StringSettingsField, } from '../types/index';
40
- export type { InspectorPanelContentProps, InspectorPanelFooterProps, InspectorPanelHeaderProps, InspectorPanelProps, KanbanBoardProps, KanbanCardSignalProps, KanbanColumnBodyProps, KanbanColumnEmptyProps, KanbanColumnHeaderProps, KanbanColumnProps, CalendarGridItem, CalendarGridProps, CalendarGridView, CalendarItemDensity, CalendarItemProps, CalendarItemTone, CalendarNavProps, ListRowActionsProps, ListRowGroupProps, ListRowLabelsProps, ListRowProps, ListRowsColumnsAlign, ListRowsColumnsAt, ListRowsProps, ListRowsSize, ListRowsVariant, NavListItem, NavListProps, NavListSection, NodeCardBorder, NodeCardProps, NodeCardTone, PageAsideCollapsible, PageAsideProps, PageAsideWidth, PageBodyGap, PageBodyLayout, PageBodyProps, PageCanvasOrientation, PageCanvasProps, PageComposerProps, PageControlsAs, PageControlsProps, PageDensity, PageHeaderMeasure, PageHeaderOverflowMenuProps, PageHeaderProps, PageProps, PageScroll, PageTimelineProps, PageWidth, PaginationProps, WorkspacePageBodyProps, WorkspacePageCompactHeaderProps, WorkspacePageHeaderProps, WorkspacePageMetricsProps, WorkspacePageMode, WorkspacePageProps, ConfirmDialogCancelVariant, ConfirmDialogProps, CopyButtonProps, KeyValueItem, KeyValueLayout, KeyValueProps, ConfirmDialogTone, DangerZoneHeadingLevel, DangerZoneProps, DataTableAlign, DataTableCollapse, DataTableColumn, DataTableNarrowRole, DataTableProps, DataTableSort, FacetFilterProps, FacetOption, AgentFilterOption, AgentFilterProps, SaveBarProps, SearchInputProps, SegmentedControlOption, SegmentedControlProps, SortableHeadProps, SortDir, StatGroupProps, StatTileProgress, StatTileProgressTone, StatTileProps, StatTileVariant, StatusBadgeProps, StatusBadgeVariant, StatusMarkerProps, StatusTone, TimelineEntryProps, TimelineProps, UnsavedChangesDialogProps, } from '../_internal/ui/patterns';
40
+ export type { InspectorPanelContentProps, InspectorPanelFooterProps, InspectorPanelHeaderProps, InspectorPanelProps, KanbanBoardProps, KanbanCardSignalProps, KanbanColumnBodyProps, KanbanColumnEmptyProps, KanbanColumnHeaderProps, KanbanColumnProps, CalendarGridItem, CalendarGridProps, CalendarGridView, CalendarItemDensity, CalendarItemProps, CalendarItemTone, CalendarNavProps, ListRowActionsProps, ListRowGroupProps, ListRowLabelsProps, ListRowProps, ListRowsColumnsAlign, ListRowsColumnsAt, ListRowsProps, ListRowsSize, ListRowsVariant, NavListItem, NavListProps, NavListSection, NodeCardBorder, NodeCardProps, NodeCardTone, PageAsideCollapsible, PageAsideProps, PageAsideWidth, PageBodyGap, PageBodyLayout, PageBodyProps, PageCanvasOrientation, PageCanvasProps, PageComposerProps, PageControlsAs, PageControlsProps, PageDensity, PageHeaderMeasure, PageHeaderProps, PageProps, PageScroll, PageTimelineProps, PageWidth, PaginationProps, WorkspacePageBodyProps, WorkspacePageCompactHeaderProps, WorkspacePageHeaderProps, WorkspacePageMetricsProps, WorkspacePageMode, WorkspacePageProps, ConfirmDialogCancelVariant, ConfirmDialogProps, CopyButtonProps, KeyValueItem, KeyValueLayout, KeyValueProps, ConfirmDialogTone, DangerZoneHeadingLevel, DangerZoneProps, DataTableAlign, DataTableCollapse, DataTableColumn, DataTableNarrowRole, DataTableProps, DataTableSort, FacetFilterProps, FacetOption, AgentFilterOption, AgentFilterProps, SaveBarProps, SearchInputProps, SegmentedControlOption, SegmentedControlProps, SortableHeadProps, SortDir, StatGroupProps, StatTileProgress, StatTileProgressTone, StatTileProps, StatTileVariant, StatusBadgeProps, StatusBadgeVariant, StatusMarkerProps, StatusTone, TimelineEntryProps, TimelineProps, UnsavedChangesDialogProps, } from '../_internal/ui/patterns';