draken 0.3.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/ACCEPTANCE.md +2 -2
  2. package/CHANGELOG.md +56 -0
  3. package/MEMORY.md +9 -5
  4. package/README.md +14 -6
  5. package/SETUP.md +1 -1
  6. package/VOICE.md +6 -2
  7. package/dist/memory/automatic.d.ts +11 -5
  8. package/dist/memory/automatic.d.ts.map +1 -1
  9. package/dist/memory/automatic.js +64 -20
  10. package/dist/memory/automatic.js.map +1 -1
  11. package/dist/memory/context.d.ts +1 -0
  12. package/dist/memory/context.d.ts.map +1 -1
  13. package/dist/memory/context.js +4 -0
  14. package/dist/memory/context.js.map +1 -1
  15. package/dist/routes/live-voice.d.ts.map +1 -1
  16. package/dist/routes/live-voice.js +7 -1
  17. package/dist/routes/live-voice.js.map +1 -1
  18. package/dist/routes/memory.d.ts.map +1 -1
  19. package/dist/routes/memory.js +12 -2
  20. package/dist/routes/memory.js.map +1 -1
  21. package/dist/routes/sync.d.ts.map +1 -1
  22. package/dist/routes/sync.js +23 -7
  23. package/dist/routes/sync.js.map +1 -1
  24. package/dist/sync/answer-references.d.ts +10 -0
  25. package/dist/sync/answer-references.d.ts.map +1 -0
  26. package/dist/sync/answer-references.js +47 -0
  27. package/dist/sync/answer-references.js.map +1 -0
  28. package/dist/sync/automatic.d.ts +7 -0
  29. package/dist/sync/automatic.d.ts.map +1 -0
  30. package/dist/sync/automatic.js +56 -0
  31. package/dist/sync/automatic.js.map +1 -0
  32. package/dist/sync/cost.d.ts +2 -1
  33. package/dist/sync/cost.d.ts.map +1 -1
  34. package/dist/sync/cost.js +10 -6
  35. package/dist/sync/cost.js.map +1 -1
  36. package/dist/sync/manager.d.ts +4 -1
  37. package/dist/sync/manager.d.ts.map +1 -1
  38. package/dist/sync/manager.js +34 -33
  39. package/dist/sync/manager.js.map +1 -1
  40. package/dist/sync/store.d.ts +8 -1
  41. package/dist/sync/store.d.ts.map +1 -1
  42. package/dist/sync/store.js +50 -4
  43. package/dist/sync/store.js.map +1 -1
  44. package/dist/sync/tree.d.ts.map +1 -1
  45. package/dist/sync/tree.js +13 -7
  46. package/dist/sync/tree.js.map +1 -1
  47. package/dist/sync/usage.d.ts +6 -0
  48. package/dist/sync/usage.d.ts.map +1 -0
  49. package/dist/sync/usage.js +91 -0
  50. package/dist/sync/usage.js.map +1 -0
  51. package/dist/types.d.ts +37 -2
  52. package/dist/types.d.ts.map +1 -1
  53. package/dist/voice/continuation.d.ts.map +1 -1
  54. package/dist/voice/continuation.js +7 -2
  55. package/dist/voice/continuation.js.map +1 -1
  56. package/dist/voice/history-delivery.d.ts +19 -0
  57. package/dist/voice/history-delivery.d.ts.map +1 -0
  58. package/dist/voice/history-delivery.js +57 -0
  59. package/dist/voice/history-delivery.js.map +1 -0
  60. package/dist/voice/history-focus.d.ts +4 -0
  61. package/dist/voice/history-focus.d.ts.map +1 -1
  62. package/dist/voice/history-focus.js +15 -0
  63. package/dist/voice/history-focus.js.map +1 -1
  64. package/dist/voice/live-context.d.ts +1 -1
  65. package/dist/voice/live-context.d.ts.map +1 -1
  66. package/dist/voice/live-context.js +2 -1
  67. package/dist/voice/live-context.js.map +1 -1
  68. package/dist/voice/live.d.ts.map +1 -1
  69. package/dist/voice/live.js +62 -28
  70. package/dist/voice/live.js.map +1 -1
  71. package/package.json +1 -1
  72. package/public/assets/index-D79D-rxm.css +1 -0
  73. package/public/assets/index-DYX9neRz.js +131 -0
  74. package/public/assets/{persona-BVIfx5k8.js → persona-CsDA3JtF.js} +1 -1
  75. package/public/index.html +3 -3
  76. package/public/persona.html +3 -3
  77. package/public/assets/index-CYCbTSh1.js +0 -131
  78. package/public/assets/index-DntUQtGK.css +0 -1
  79. /package/public/assets/{index-BQFBaSKm.js → index-B13h0MjX.js} +0 -0
@@ -1,131 +0,0 @@
1
- var vs=Object.defineProperty;var Ze=t=>{throw TypeError(t)};var js=(t,s,n)=>s in t?vs(t,s,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[s]=n;var A=(t,s,n)=>js(t,typeof s!="symbol"?s+"":s,n),Xe=(t,s,n)=>s.has(t)||Ze("Cannot "+n);var u=(t,s,n)=>(Xe(t,s,"read from private field"),n?n.call(t):s.get(t)),z=(t,s,n)=>s.has(t)?Ze("Cannot add the same private member more than once"):s instanceof WeakSet?s.add(t):s.set(t,n),q=(t,s,n,r)=>(Xe(t,s,"write to private field"),r?r.call(t,n):s.set(t,n),n);import{r as o,j as e,P as ws,R as bs,a as ks}from"./index-BQFBaSKm.js";/**
2
- * @license lucide-react v0.468.0 - ISC
3
- *
4
- * This source code is licensed under the ISC license.
5
- * See the LICENSE file in the root directory of this source tree.
6
- */const Ns=t=>t.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase(),cs=(...t)=>t.filter((s,n,r)=>!!s&&s.trim()!==""&&r.indexOf(s)===n).join(" ").trim();/**
7
- * @license lucide-react v0.468.0 - ISC
8
- *
9
- * This source code is licensed under the ISC license.
10
- * See the LICENSE file in the root directory of this source tree.
11
- */var Ss={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};/**
12
- * @license lucide-react v0.468.0 - ISC
13
- *
14
- * This source code is licensed under the ISC license.
15
- * See the LICENSE file in the root directory of this source tree.
16
- */const Cs=o.forwardRef(({color:t="currentColor",size:s=24,strokeWidth:n=2,absoluteStrokeWidth:r,className:i="",children:l,iconNode:a,...g},d)=>o.createElement("svg",{ref:d,...Ss,width:s,height:s,stroke:t,strokeWidth:r?Number(n)*24/Number(s):n,className:cs("lucide",i),...g},[...a.map(([S,c])=>o.createElement(S,c)),...Array.isArray(l)?l:[l]]));/**
17
- * @license lucide-react v0.468.0 - ISC
18
- *
19
- * This source code is licensed under the ISC license.
20
- * See the LICENSE file in the root directory of this source tree.
21
- */const M=(t,s)=>{const n=o.forwardRef(({className:r,...i},l)=>o.createElement(Cs,{ref:l,iconNode:s,className:cs(`lucide-${Ns(t)}`,r),...i}));return n.displayName=`${t}`,n};/**
22
- * @license lucide-react v0.468.0 - ISC
23
- *
24
- * This source code is licensed under the ISC license.
25
- * See the LICENSE file in the root directory of this source tree.
26
- */const Es=M("ArrowLeft",[["path",{d:"m12 19-7-7 7-7",key:"1l729n"}],["path",{d:"M19 12H5",key:"x3x0zl"}]]);/**
27
- * @license lucide-react v0.468.0 - ISC
28
- *
29
- * This source code is licensed under the ISC license.
30
- * See the LICENSE file in the root directory of this source tree.
31
- */const es=M("ArrowRight",[["path",{d:"M5 12h14",key:"1ays0h"}],["path",{d:"m12 5 7 7-7 7",key:"xquz4c"}]]);/**
32
- * @license lucide-react v0.468.0 - ISC
33
- *
34
- * This source code is licensed under the ISC license.
35
- * See the LICENSE file in the root directory of this source tree.
36
- */const ls=M("ArrowUp",[["path",{d:"m5 12 7-7 7 7",key:"hav0vg"}],["path",{d:"M12 19V5",key:"x0mq9r"}]]);/**
37
- * @license lucide-react v0.468.0 - ISC
38
- *
39
- * This source code is licensed under the ISC license.
40
- * See the LICENSE file in the root directory of this source tree.
41
- */const Ts=M("AudioLines",[["path",{d:"M2 10v3",key:"1fnikh"}],["path",{d:"M6 6v11",key:"11sgs0"}],["path",{d:"M10 3v18",key:"yhl04a"}],["path",{d:"M14 8v7",key:"3a1oy3"}],["path",{d:"M18 5v13",key:"123xd1"}],["path",{d:"M22 10v3",key:"154ddg"}]]);/**
42
- * @license lucide-react v0.468.0 - ISC
43
- *
44
- * This source code is licensed under the ISC license.
45
- * See the LICENSE file in the root directory of this source tree.
46
- */const As=M("Check",[["path",{d:"M20 6 9 17l-5-5",key:"1gmf2c"}]]);/**
47
- * @license lucide-react v0.468.0 - ISC
48
- *
49
- * This source code is licensed under the ISC license.
50
- * See the LICENSE file in the root directory of this source tree.
51
- */const Ps=M("CircleAlert",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["line",{x1:"12",x2:"12",y1:"8",y2:"12",key:"1pkeuh"}],["line",{x1:"12",x2:"12.01",y1:"16",y2:"16",key:"4dfq90"}]]);/**
52
- * @license lucide-react v0.468.0 - ISC
53
- *
54
- * This source code is licensed under the ISC license.
55
- * See the LICENSE file in the root directory of this source tree.
56
- */const _s=M("ExternalLink",[["path",{d:"M15 3h6v6",key:"1q9fwt"}],["path",{d:"M10 14 21 3",key:"gplh6r"}],["path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6",key:"a6xqqp"}]]);/**
57
- * @license lucide-react v0.468.0 - ISC
58
- *
59
- * This source code is licensed under the ISC license.
60
- * See the LICENSE file in the root directory of this source tree.
61
- */const Is=M("Headphones",[["path",{d:"M3 14h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-7a9 9 0 0 1 18 0v7a2 2 0 0 1-2 2h-1a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2h3",key:"1xhozi"}]]);/**
62
- * @license lucide-react v0.468.0 - ISC
63
- *
64
- * This source code is licensed under the ISC license.
65
- * See the LICENSE file in the root directory of this source tree.
66
- */const Ds=M("Keyboard",[["path",{d:"M10 8h.01",key:"1r9ogq"}],["path",{d:"M12 12h.01",key:"1mp3jc"}],["path",{d:"M14 8h.01",key:"1primd"}],["path",{d:"M16 12h.01",key:"1l6xoz"}],["path",{d:"M18 8h.01",key:"emo2bl"}],["path",{d:"M6 8h.01",key:"x9i8wu"}],["path",{d:"M7 16h10",key:"wp8him"}],["path",{d:"M8 12h.01",key:"czm47f"}],["rect",{width:"20",height:"16",x:"2",y:"4",rx:"2",key:"18n3k1"}]]);/**
67
- * @license lucide-react v0.468.0 - ISC
68
- *
69
- * This source code is licensed under the ISC license.
70
- * See the LICENSE file in the root directory of this source tree.
71
- */const Ms=M("Lock",[["rect",{width:"18",height:"11",x:"3",y:"11",rx:"2",ry:"2",key:"1w4ew1"}],["path",{d:"M7 11V7a5 5 0 0 1 10 0v4",key:"fwvmzm"}]]);/**
72
- * @license lucide-react v0.468.0 - ISC
73
- *
74
- * This source code is licensed under the ISC license.
75
- * See the LICENSE file in the root directory of this source tree.
76
- */const qs=M("LogIn",[["path",{d:"M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4",key:"u53s6r"}],["polyline",{points:"10 17 15 12 10 7",key:"1ail0h"}],["line",{x1:"15",x2:"3",y1:"12",y2:"12",key:"v6grx8"}]]);/**
77
- * @license lucide-react v0.468.0 - ISC
78
- *
79
- * This source code is licensed under the ISC license.
80
- * See the LICENSE file in the root directory of this source tree.
81
- */const Rs=M("LogOut",[["path",{d:"M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4",key:"1uf3rs"}],["polyline",{points:"16 17 21 12 16 7",key:"1gabdz"}],["line",{x1:"21",x2:"9",y1:"12",y2:"12",key:"1uyos4"}]]);/**
82
- * @license lucide-react v0.468.0 - ISC
83
- *
84
- * This source code is licensed under the ISC license.
85
- * See the LICENSE file in the root directory of this source tree.
86
- */const ds=M("MessageSquare",[["path",{d:"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z",key:"1lielz"}]]);/**
87
- * @license lucide-react v0.468.0 - ISC
88
- *
89
- * This source code is licensed under the ISC license.
90
- * See the LICENSE file in the root directory of this source tree.
91
- */const Ls=M("MicOff",[["line",{x1:"2",x2:"22",y1:"2",y2:"22",key:"a6p6uj"}],["path",{d:"M18.89 13.23A7.12 7.12 0 0 0 19 12v-2",key:"80xlxr"}],["path",{d:"M5 10v2a7 7 0 0 0 12 5",key:"p2k8kg"}],["path",{d:"M15 9.34V5a3 3 0 0 0-5.68-1.33",key:"1gzdoj"}],["path",{d:"M9 9v3a3 3 0 0 0 5.12 2.12",key:"r2i35w"}],["line",{x1:"12",x2:"12",y1:"19",y2:"22",key:"x3vr5v"}]]);/**
92
- * @license lucide-react v0.468.0 - ISC
93
- *
94
- * This source code is licensed under the ISC license.
95
- * See the LICENSE file in the root directory of this source tree.
96
- */const Os=M("Mic",[["path",{d:"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z",key:"131961"}],["path",{d:"M19 10v2a7 7 0 0 1-14 0v-2",key:"1vc78b"}],["line",{x1:"12",x2:"12",y1:"19",y2:"22",key:"x3vr5v"}]]);/**
97
- * @license lucide-react v0.468.0 - ISC
98
- *
99
- * This source code is licensed under the ISC license.
100
- * See the LICENSE file in the root directory of this source tree.
101
- */const $s=M("PhoneOff",[["path",{d:"M10.68 13.31a16 16 0 0 0 3.41 2.6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7 2 2 0 0 1 1.72 2v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.42 19.42 0 0 1-3.33-2.67m-2.67-3.34a19.79 19.79 0 0 1-3.07-8.63A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91",key:"z86iuo"}],["line",{x1:"22",x2:"2",y1:"2",y2:"22",key:"11kh81"}]]);/**
102
- * @license lucide-react v0.468.0 - ISC
103
- *
104
- * This source code is licensed under the ISC license.
105
- * See the LICENSE file in the root directory of this source tree.
106
- */const Ye=M("Phone",[["path",{d:"M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z",key:"foiqr5"}]]);/**
107
- * @license lucide-react v0.468.0 - ISC
108
- *
109
- * This source code is licensed under the ISC license.
110
- * See the LICENSE file in the root directory of this source tree.
111
- */const zs=M("RefreshCw",[["path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8",key:"v9h5vc"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}],["path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16",key:"3uifl3"}],["path",{d:"M8 16H3v5",key:"1cv678"}]]);/**
112
- * @license lucide-react v0.468.0 - ISC
113
- *
114
- * This source code is licensed under the ISC license.
115
- * See the LICENSE file in the root directory of this source tree.
116
- */const Fs=M("Settings",[["path",{d:"M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z",key:"1qme2f"}],["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}]]);/**
117
- * @license lucide-react v0.468.0 - ISC
118
- *
119
- * This source code is licensed under the ISC license.
120
- * See the LICENSE file in the root directory of this source tree.
121
- */const hs=M("Square",[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}]]);/**
122
- * @license lucide-react v0.468.0 - ISC
123
- *
124
- * This source code is licensed under the ISC license.
125
- * See the LICENSE file in the root directory of this source tree.
126
- */const Hs=M("User",[["path",{d:"M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2",key:"975kel"}],["circle",{cx:"12",cy:"7",r:"4",key:"17ys0d"}]]);/**
127
- * @license lucide-react v0.468.0 - ISC
128
- *
129
- * This source code is licensed under the ISC license.
130
- * See the LICENSE file in the root directory of this source tree.
131
- */const Ke=M("X",[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]]),us=o.createContext(null),Le="draken_token",Oe="draken_username";function Us({children:t}){const[s,n]=o.useState({isAuthenticated:!1,isLoading:!0,authEnabled:!0,username:null,token:null}),r=o.useCallback(async()=>{n(a=>({...a,isLoading:!0}));try{if(!(await(await fetch("/api/auth/status")).json()).enabled){n({isAuthenticated:!0,isLoading:!1,authEnabled:!1,username:null,token:null});return}const d=localStorage.getItem(Le),S=localStorage.getItem(Oe);if(!d){n({isAuthenticated:!1,isLoading:!1,authEnabled:!0,username:null,token:null});return}(await fetch("/api/auth/verify",{headers:{Authorization:`Bearer ${d}`}})).ok?n({isAuthenticated:!0,isLoading:!1,authEnabled:!0,username:S,token:d}):(localStorage.removeItem(Le),localStorage.removeItem(Oe),n({isAuthenticated:!1,isLoading:!1,authEnabled:!0,username:null,token:null}))}catch(a){console.error("Auth check failed:",a),n({isAuthenticated:!1,isLoading:!1,authEnabled:!0,username:null,token:null})}},[]),i=async(a,g)=>{const d=await fetch("/api/auth/login",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({username:a,password:g})});if(!d.ok){const c=await d.json();throw new Error(c.error||"Login failed")}const S=await d.json();localStorage.setItem(Le,S.token),localStorage.setItem(Oe,S.username),n({isAuthenticated:!0,isLoading:!1,authEnabled:!0,username:S.username,token:S.token})},l=()=>{localStorage.removeItem(Le),localStorage.removeItem(Oe),n({isAuthenticated:!1,isLoading:!1,authEnabled:!0,username:null,token:null})};return o.useEffect(()=>{r()},[r]),e.jsx(us.Provider,{value:{...s,login:i,logout:l,checkAuth:r},children:t})}function ps(){const t=o.useContext(us);if(!t)throw new Error("useAuth must be used within an AuthProvider");return t}function Vs(){const{login:t}=ps(),[s,n]=o.useState(""),[r,i]=o.useState(""),[l,a]=o.useState(null),[g,d]=o.useState(!1),S=async c=>{c.preventDefault(),a(null),d(!0);try{await t(s,r)}catch(j){a(j instanceof Error?j.message:"Login failed")}finally{d(!1)}};return e.jsx("div",{className:"login-page",children:e.jsxs("div",{className:"login-card",children:[e.jsxs("div",{className:"login-header",children:[e.jsx("img",{src:"/favicon.png",alt:"Draken",className:"login-logo"}),e.jsx("h1",{children:"Draken"}),e.jsx("p",{className:"login-subtitle",children:"Your engineering sync across pi sessions"})]}),e.jsxs("form",{onSubmit:S,className:"login-form",children:[l&&e.jsxs("div",{className:"login-error",role:"alert",children:[e.jsx(Ps,{size:16}),l]}),e.jsxs("div",{className:"form-group",children:[e.jsx("label",{htmlFor:"username",children:"Username"}),e.jsxs("div",{className:"input-with-icon",children:[e.jsx(Hs,{size:18,className:"input-icon"}),e.jsx("input",{id:"username",type:"text",className:"input",placeholder:"Enter username",value:s,onChange:c=>n(c.target.value),autoComplete:"username",autoFocus:!0})]})]}),e.jsxs("div",{className:"form-group",children:[e.jsx("label",{htmlFor:"password",children:"Password"}),e.jsxs("div",{className:"input-with-icon",children:[e.jsx(Ms,{size:18,className:"input-icon"}),e.jsx("input",{id:"password",type:"password",className:"input",placeholder:"Enter password",value:r,onChange:c=>i(c.target.value),autoComplete:"current-password"})]})]}),e.jsx("button",{type:"submit",className:"btn btn-primary btn-lg login-btn",disabled:g||!s||!r,children:g?e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"spinner spinner-sm"})," Signing in..."]}):e.jsxs(e.Fragment,{children:[e.jsx(qs,{size:18})," Sign In"]})})]})]})})}async function P(t,s="GET",n,r){const i=localStorage.getItem("draken_token"),l=await fetch(`/api${t}`,{method:s,signal:r,headers:{"Content-Type":"application/json",...i?{Authorization:`Bearer ${i}`}:{}},body:n===void 0?void 0:JSON.stringify(n)});if(l.status===401)throw localStorage.removeItem("draken_token"),localStorage.removeItem("draken_username"),window.location.reload(),new Error("Authentication required");if(l.status===204)return;const a=await l.json();if(!l.ok)throw new Error(a.error||`Request failed (${l.status})`);return a}const Bs=(t=!1)=>P(`/setup${t?"?refresh=1":""}`),Ys=()=>P("/settings/auto-index"),Ks=t=>P("/settings/auto-index","PATCH",{enabled:t}),Ge=t=>P(`/home${t?`?before=${t}`:""}`),Gs=t=>P("/syncs/start-call","POST",{request_id:t}),Ws=t=>P("/syncs/start-chat","POST",{request_id:t}),Qs=(t,s,n)=>P(`/syncs/${t}/chat/messages`,"POST",{message:s,request_id:n}),ss=t=>P(`/syncs/${t}/recap`,"POST"),ts=()=>P("/overview"),Js=()=>P("/scan","POST"),Zs=(t,s)=>P(`/agents/${encodeURIComponent(t)}`,"PATCH",{enabled:s}),Xs=(t,s)=>P(`/sessions/${encodeURIComponent(t)}`,"PATCH",{included:s}),Ue=t=>P(`/syncs/${t}`),et=t=>P(`/syncs/${t}/progress`),ns=(t,s)=>P(`/syncs/${t}/call-readiness`,"GET",void 0,s),st=(t,s)=>P(`/syncs/${t}/chat-readiness`,"GET",void 0,s),tt=t=>P(`/syncs/${t}/prepare-call`,"POST"),nt=(t,s)=>P(`/syncs/${t}/tree/${s}`),at=t=>P(`/syncs/${t}/expand`,"POST"),rt=t=>P(`/syncs/${t}/cancel`,"POST"),it=t=>P(`/syncs/${t}/briefing`,"POST"),ot=(t,s)=>P(`/syncs/${t}/messages`,"POST",{message:s}),ct=t=>P("/memory/progress","GET",void 0,t),lt=(t,s)=>P("/memory/search","POST",t,s),dt=(t,s=0)=>P(`/memory/records/${encodeURIComponent(t)}?offset=${s}`),Se=(t,s,n)=>P(`/syncs/${t}/notes`,"PATCH",{decisions:s,carry_forward:n}),ht=(t,s,n)=>P(`/syncs/${t}/complete`,"POST",{decisions:s,carry_forward:n,reviewed:!0}),ut=t=>P(`/syncs/${t}/discard`,"POST"),Ce=25;function as({items:t,title:s}){const[n,r]=o.useState(0),[i,l]=o.useState(""),[a,g]=o.useState("");if(o.useEffect(()=>{const f=w=>{const v=w.detail,b=t.findIndex(x=>x.ref===v);b<0||(l(""),r(Math.floor(b/Ce)),g(v))};return window.addEventListener("draken:evidence",f),()=>window.removeEventListener("draken:evidence",f)},[t]),o.useEffect(()=>{if(!a)return;const f=document.getElementById(`evidence-${a}`);f&&(f.open=!0,f.scrollIntoView({behavior:"smooth",block:"center"}),g(""))},[a,n,i]),!t.length)return null;const d=i.toLocaleLowerCase(),S=d?t.filter(f=>`${f.ref} ${f.session_name} ${f.cwd} ${f.text}`.toLocaleLowerCase().includes(d)):t,c=Math.max(1,Math.ceil(S.length/Ce)),j=Math.min(n,c-1);return e.jsxs("section",{className:"evidence-section",children:[e.jsxs("h3",{children:[s," ",e.jsx("span",{className:"count",children:t.length})]}),t.length>Ce&&e.jsxs("div",{className:"evidence-controls",children:[e.jsx("input",{className:"input","aria-label":`Search ${s}`,placeholder:"Find a topic, workspace, or evidence ID…",value:i,onChange:f=>{l(f.target.value),r(0)}}),e.jsxs("div",{className:"pagination",children:[e.jsx("button",{className:"btn btn-secondary",disabled:j===0,onClick:()=>r(j-1),children:"Previous"}),e.jsxs("span",{children:[j+1," / ",c," · ",S.length," entries"]}),e.jsx("button",{className:"btn btn-secondary",disabled:j>=c-1,onClick:()=>r(j+1),children:"Next"})]})]}),e.jsx("div",{className:"evidence-list",children:S.slice(j*Ce,(j+1)*Ce).map(f=>e.jsxs("details",{className:"evidence",id:`evidence-${f.ref}`,children:[e.jsxs("summary",{children:[e.jsx("span",{className:"reference",children:f.ref}),e.jsxs("span",{className:"evidence-title",children:[e.jsxs("strong",{children:[f.agent&&f.agent!=="pi"&&`${f.agent} · `,f.session_name||f.cwd.split("/").filter(Boolean).pop()||f.cwd]}),e.jsx("span",{children:f.unavailable?"Original session source unavailable":f.text.slice(0,130)})]}),e.jsx("span",{className:"role-label",children:f.role})]}),e.jsxs("div",{className:"evidence-body",children:[e.jsxs("dl",{children:[e.jsx("dt",{children:"Workspace"}),e.jsx("dd",{children:f.cwd}),e.jsx("dt",{children:"Session"}),e.jsx("dd",{children:f.session_id}),e.jsx("dt",{children:"Source"}),e.jsx("dd",{children:f.source_path}),e.jsx("dt",{children:"Entry"}),e.jsxs("dd",{children:[f.entry_id," · ",f.timestamp]})]}),f.unavailable?e.jsx("p",{className:"alert warning",role:"status",children:f.unavailable}):e.jsx("pre",{children:f.text})]})]},f.ref))})]})}function Ee({text:t,evidence:s}){const n=new Set(s.map(r=>r.ref));return e.jsx("div",{className:"prose",children:t.split(/(\[(?:[EC]\d+|H[a-f0-9]{24})\])/g).map((r,i)=>{const l=r.slice(1,-1);return/^H[a-f0-9]{24}$/.test(l)?e.jsxs("a",{className:"citation",href:`/history/${l}`,target:"_blank",rel:"noopener noreferrer","aria-label":`Inspect historical source ${l}`,children:["[history ",l.slice(-6),"]"]},i):!/^\[(E|C)\d+\]$/.test(r)||!n.has(l)?e.jsx("span",{children:r},i):e.jsx("button",{className:"citation",onClick:()=>window.dispatchEvent(new CustomEvent("draken:evidence",{detail:l})),"aria-label":`Inspect evidence ${l}`,children:r},i)})})}function pt({syncId:t,progress:s,evidence:n,onCancel:r,onResume:i,resumeEnabled:l}){var m;const[a,g]=o.useState(new Set),[d,S]=o.useState(null),[c,j]=o.useState(""),[f,w]=o.useState(!1),v=s.run;if(o.useEffect(()=>{S(null),g(new Set)},[v==null?void 0:v.id]),!v)return null;const b=!s.busy&&["failed","cancelled","interrupted"].includes(v.status),x=new Map(s.nodes.map(y=>[y.key,y])),_=new Set(s.nodes.flatMap(y=>y.children)),T=s.nodes.filter(y=>!_.has(y.key)),p=async y=>{w(!0),j("");try{S(await nt(t,y.key))}catch(E){j(E instanceof Error?E.message:"Could not load summary")}finally{w(!1)}},N=(y,E=new Set)=>{if(E.has(y.key))return null;const F=new Set([...E,y.key]),X=a.has(y.key);return e.jsxs("li",{children:[e.jsxs("div",{className:"tree-node",children:[e.jsx("button",{className:"tree-toggle","aria-label":`Expand ${y.label}`,disabled:!y.children.length,onClick:()=>g(I=>{const R=new Set(I);return R.has(y.key)?R.delete(y.key):R.add(y.key),R}),children:y.children.length?X?"▾":"▸":"·"}),e.jsxs("button",{className:"tree-label",disabled:!["done","cached"].includes(y.status)||f,onClick:()=>void p(y),title:y.error||y.label,children:[e.jsx("span",{className:"role-label",children:y.kind})," ",y.label]}),e.jsx("span",{className:`status ${y.status}`,children:y.status})]}),X&&e.jsx("ul",{children:y.children.map(I=>x.has(I)?N(x.get(I),F):null)})]},y.key)};return e.jsxs("section",{className:"card tree-card",children:[e.jsxs("div",{className:"section-heading",children:[e.jsx("h2",{children:"Summary tree"}),e.jsx("span",{className:`status ${v.status}`,children:v.status})]}),e.jsx("p",{className:"small muted",children:"Complete source batches → compact reconciliation → final verdict"}),e.jsx("progress",{max:Math.max(1,v.total_entries),value:v.processed_entries,"aria-label":"Evidence compression progress"}),e.jsxs("div",{className:"tree-stats",children:[e.jsxs("span",{children:[v.processed_entries," / ",v.total_entries," entries processed"]}),e.jsxs("span",{children:[v.invocations," / ",v.max_invocations," pi invocations"]}),e.jsxs("span",{children:[v.cache_hits," cached nodes reused"]})]}),!!((m=v.metrics)!=null&&m.length)&&e.jsxs("details",{className:"small",children:[e.jsx("summary",{children:"Model request timing"}),e.jsxs("p",{children:[(v.metrics.reduce((y,E)=>y+E.elapsed_ms,0)/1e3).toFixed(1)," seconds across ",v.metrics.length," requests · ",v.metrics.reduce((y,E)=>y+E.input_tokens_estimate,0).toLocaleString()," estimated input tokens."]}),e.jsx("p",{className:"muted",children:"Includes pi startup and provider waiting/generation, not separately measured. Token counts are local planning estimates with input headroom, not billed usage. A completed request can still fail summary validation."}),e.jsx("ul",{children:v.metrics.map((y,E)=>e.jsxs("li",{children:[y.stage||y.task,y.repair?" (repair)":""," · ",(y.elapsed_ms/1e3).toFixed(1)," s · ",y.status]},E))})]}),e.jsxs("p",{className:"small",children:[b?"Stopped at: ":"",v.stage]}),v.question&&e.jsxs("p",{className:"small muted",children:["Question: ",v.question]}),v.error&&e.jsxs("div",{className:"alert error",role:"alert",children:[e.jsx("strong",{children:"Last run’s error:"})," ",v.error]}),b&&e.jsxs("div",{className:"alert warning",children:[e.jsx("strong",{children:"Generation stopped. No model calls are running."}),e.jsxs("p",{className:"small",children:[v.processed_entries<v.total_entries?`${v.total_entries-v.processed_entries} entries still need compression.`:"Raw chunks were processed, but reconciliation or the final reply did not finish."," Successful chunks are cached; nothing was marked reviewed."]}),i&&e.jsxs(e.Fragment,{children:[e.jsx("p",{className:"small",children:"Resume to continue from cached chunks instead of generating them again."}),e.jsx("button",{className:"btn btn-primary",disabled:!l,onClick:i,children:"Resume generation"})]})]}),s.busy&&e.jsx("button",{className:"btn btn-secondary",onClick:r,children:"Cancel generation"}),e.jsxs("details",{className:"tree-browser",children:[e.jsxs("summary",{children:["Inspect ",s.nodes.length," summary nodes"]}),e.jsx("ul",{children:T.map(y=>N(y))})]}),c&&e.jsx("p",{role:"alert",className:"error",children:c}),d&&e.jsxs("div",{className:"node-inspector",children:[e.jsxs("div",{className:"section-heading",children:[e.jsx("h3",{children:d.label}),e.jsx("button",{className:"btn btn-ghost",onClick:()=>S(null),children:"Close"})]}),"observations"in d.output?e.jsxs(e.Fragment,{children:[d.output.observations.map((y,E)=>e.jsxs("div",{className:"node-observation",children:[e.jsx("strong",{children:y.topic})," ",e.jsx("span",{className:"status",children:y.state}),e.jsx(Ee,{text:`${y.summary} ${y.evidence.map(F=>d.refs[F]?`[${d.refs[F]}]`:"[source unavailable]").join(" ")}`,evidence:n})]},E)),d.output.limitations.map((y,E)=>e.jsx("p",{className:"muted small",children:y},E))]}):d.output.groups.map((y,E)=>e.jsxs("p",{className:"small",children:[y.topic," · ",y.members.length," related observations"]},E))]})]})}function ms(){const t=crypto.getRandomValues(new Uint8Array(16));t[6]=t[6]&15|64,t[8]=t[8]&63|128;const s=[...t].map(n=>n.toString(16).padStart(2,"0")).join("");return`${s.slice(0,8)}-${s.slice(8,12)}-${s.slice(12,16)}-${s.slice(16,20)}-${s.slice(20)}`}const We={phase:"connecting",muted:!1,microphone:!1,voiceInterruption:!1,question:"",answer:"",evidence:[],error:"",notice:"",startedAt:0,turnId:0,replyPendingSince:0,historyReady:!1};function gs(t=!0){const s=localStorage.getItem("draken_token");return{...t?{"Content-Type":"application/json"}:{},...s?{Authorization:`Bearer ${s}`}:{}}}async function Z(t,s={}){const n=await fetch(`/api/voice${t}`,{...s,headers:gs()});if(!n.ok){const r=await n.json().catch(()=>({}));throw new Error(r.error||(n.status===401?"Sign in again to use the call.":"The live connection failed."))}return n.status===204?void 0:n.json()}function fs({cost:t}){if(!t)return null;const s=t.usd===null?"unavailable":t.usd>0&&t.usd<1e-6?"<$0.000001":new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",minimumFractionDigits:2,maximumFractionDigits:t.usd<.01?6:2}).format(t.usd),n="Sync preparation only: summaries, consolidation, preparation recaps and final briefing, including retries. Excludes later questions, calls and conversation recaps. API-equivalent estimate from pi usage and catalog prices, not a subscription charge or invoice.",r=t.usd===null?" Usage/pricing was not captured or is unavailable for this preparation.":t.complete?"":" Partial total: some preparation usage/pricing is missing or work is still running.";return e.jsxs("span",{className:"sync-cost small muted",title:n+r,children:["Est. cost: ",s,t.usd!==null&&!t.complete?" (partial)":""]})}function xs({active:t=!0,firstRun:s=!1,always:n=!1,onReady:r,onTextReady:i}){const[l,a]=o.useState(null),[g,d]=o.useState(null),[S,c]=o.useState(""),[j,f]=o.useState(!1),[w,v]=o.useState(0);if(o.useEffect(()=>{if(!t)return;let x=!0;const _=async(p=!1)=>{f(!0);try{const[N,m]=await Promise.all([Bs(p),Z("/status").catch(()=>null)]);if(!x)return;a(N),d(m),c(m?"":"Voice status is unavailable. Configured text chat can still be used."),r==null||r(N.pi.state==="configured"&&!!(m!=null&&m.installed)),i==null||i(N.pi.state==="configured")}catch{x&&(c("Could not check setup or reach Draken. The last displayed state may be stale. Check the server terminal, then retry."),r==null||r(!1),i==null||i(!1))}finally{x&&f(!1)}};_(w>0);const T=setInterval(()=>void _(),6e4);return()=>{x=!1,clearInterval(T)}},[t,w,r,i]),!t||!n&&!s&&!S&&(l==null?void 0:l.pi.state)==="configured"&&(g!=null&&g.installed))return null;const b=l==null?void 0:l.pi;return e.jsxs("section",{className:"setup-panel","aria-label":"Draken setup",children:[e.jsx("h2",{children:s?"First-time setup":"Runtime & sign-in"}),e.jsx("p",{className:"small muted",children:"Draken reads agent histories, but pi runs summaries and text chat. Voice uses a separate ChatGPT sign-in. Setup and login are explicit terminal commands—not browser downloads or credential forms."}),!l&&!S&&e.jsx("p",{className:"small",role:"status",children:"Checking setup…"}),b&&e.jsxs(e.Fragment,{children:[e.jsxs("p",{children:[e.jsxs("strong",{children:["Summarization: ",b.state==="configured"?"credentials configured":b.state==="missing"?"pi not found":b.state==="needs_login"?"sign-in needed":"needs attention"]}),e.jsxs("span",{className:"small muted",children:[" · ",b.source==="managed"?"Draken-private pi":"Existing / external pi",b.version&&` ${b.version}`]})]}),e.jsx("p",{className:"small",children:b.message}),b.state!=="configured"&&e.jsxs("div",{className:"setup-commands",children:[["missing","incompatible"].includes(b.state)&&e.jsxs("p",{children:[e.jsx("code",{children:"draken setup"})," — install a pinned, private pi after confirmation. An explicit ",e.jsx("code",{children:"DRAKEN_PI_BIN"})," must be fixed or unset first."]}),e.jsxs("p",{children:[e.jsx("code",{children:"draken login"})," — open pi; type ",e.jsx("code",{children:"/login"}),", follow its prompts, then ",e.jsx("code",{children:"/quit"}),"."]}),e.jsxs("p",{children:[e.jsx("code",{children:"draken doctor"})," — inspect configuration without a generation request."]})]}),e.jsx("ul",{className:"small muted",children:b.models.map(x=>e.jsxs("li",{children:[x.model," · ",x.state.replace(/_/g," ")]},x.model))}),e.jsxs("p",{className:"small muted source-path",children:["Pi credential directory: ",b.agent_dir]})]}),g&&e.jsx("p",{children:e.jsxs("strong",{children:["ChatGPT voice: ",g.installed?"helper and sign-in configured":"setup needed"]})}),g&&!g.installed&&e.jsxs("div",{className:"setup-commands",children:[e.jsxs("p",{children:[e.jsx("code",{children:"draken voice setup"})," — install the native helper."]}),e.jsxs("p",{children:[e.jsx("code",{children:"draken voice login"})," — use its separate official ChatGPT sign-in. No pi tokens are copied."]})]}),(n||s||(b==null?void 0:b.state)!=="configured"||!(g!=null&&g.installed))&&e.jsxs(e.Fragment,{children:[e.jsxs("p",{className:"small muted",children:["Run commands on the server as its user, with the same environment. After login, click Check setup again. Keep the server terminal open; Ctrl+C stops it. ",e.jsx("code",{children:"draken status"})," checks connectivity."]}),l&&e.jsxs("p",{className:"small muted source-path",children:["Draken data: ",l.data_dir]}),e.jsxs("p",{className:"small muted",children:["Choose sources in ",e.jsx("strong",{children:"Settings → Agents & sessions"}),", then ",e.jsx("strong",{children:"Sync with Draken"}),". Source scanning works before sign-in. Credential presence does not verify model access, billing or voice playback."]})]}),S&&e.jsx("p",{className:"small",role:"alert",children:S}),e.jsx("button",{type:"button",className:"btn btn-secondary",disabled:j,onClick:()=>v(x=>x+1),children:j?"Checking…":"Check setup again"})]})}const ue=(t,s,n)=>{t.button||t.metaKey||t.ctrlKey||t.shiftKey||t.altKey||(t.preventDefault(),s(n))},mt=t=>new Date(t).toLocaleString(void 0,{dateStyle:"medium",timeStyle:"short"});function gt({navigate:t}){const[s,n]=o.useState(null),[r,i]=o.useState(""),[l,a]=o.useState(""),[g,d]=o.useState(""),[S,c]=o.useState(!1),[j,f]=o.useState(!1),w=o.useRef(!0),v=o.useRef(!1),b=o.useRef(),x=async()=>{const p=await Ge();w.current&&n(N=>N&&N.syncs.length>20?{...p,syncs:[...p.syncs,...N.syncs.filter(m=>{var y;return m.id<((y=p.syncs[p.syncs.length-1])==null?void 0:y.id)})],next_cursor:N.next_cursor}:p)};o.useEffect(()=>{w.current=!0,x().catch(N=>a(N.message)),window.isSecureContext||Z("/status").then(N=>{if(w.current&&N.httpsPort){const m=new URL("/",location.href);m.protocol="https:",m.port=String(N.httpsPort),d(m.href)}}).catch(()=>{});const p=setInterval(()=>{v.current||x().catch(()=>{})},4e3);return()=>{w.current=!1,clearInterval(p)}},[]);const _=async(p="call")=>{if(!v.current){v.current=!0,i("Collecting new activity…"),a(""),b.current||(b.current=ms());try{if(p==="call"){const m=await Z("/status");if(!m.installed)throw new Error("Voice is not ready on this server. Complete voice setup before starting a sync call.");if(m.activeCall)throw new Error("End the existing call before starting another sync.")}const N=await(p==="chat"?Ws:Gs)(b.current);w.current&&t(`/syncs/${N.sync.id}${p==="chat"?"/chat":""}`,p==="call")}catch(N){w.current&&a(N instanceof Error?N.message:"Could not start the sync")}finally{v.current=!1,w.current&&i("")}}},T=!!(!S||r||s!=null&&s.busy||s!=null&&s.active_call);return e.jsxs("main",{className:"sync-home",children:[e.jsxs("div",{className:"page-heading",children:[e.jsxs("div",{children:[e.jsx("h1",{children:"Pick up where you left off."}),e.jsx("p",{className:"muted",children:"New activity. A little memory. One conversation."})]}),e.jsxs("div",{className:"conversation-actions",children:[e.jsxs("button",{className:"btn btn-secondary",disabled:!s||!j||!!(r||s!=null&&s.busy||s!=null&&s.active_call),onClick:()=>void _("chat"),children:[e.jsx(ds,{size:17}),"Chat instead"]}),g?e.jsxs("a",{className:"btn btn-primary",href:g,children:["Open secure Draken",e.jsx(es,{size:17})]}):e.jsxs("button",{className:"btn btn-primary",disabled:!s||T||!window.isSecureContext,onClick:()=>void _(),children:[e.jsx(Ye,{size:17}),"Sync with Draken"]})]})]}),!window.isSecureContext&&e.jsx("p",{className:"small muted",children:"Use trusted HTTPS or localhost for the combined sync and call."}),e.jsx("p",{className:"home-hint muted small",children:"New entries → a prepared snapshot → your conversation. Chat uses your configured text model, without a microphone. Previous syncs come along as short recaps."}),e.jsxs("div",{className:"home-counts","aria-label":"Sync tracking",children:[e.jsxs("span",{children:[e.jsx("strong",{children:(s==null?void 0:s.available)??"—"})," waiting"]}),e.jsxs("span",{children:[e.jsx("strong",{children:(s==null?void 0:s.included_unreviewed)??"—"})," included, not reviewed"]}),e.jsxs("span",{children:[e.jsx("strong",{children:(s==null?void 0:s.covered)??"—"})," reviewed"]})]}),r&&e.jsxs("p",{role:"status",className:"working",children:[e.jsx("span",{className:"spinner"}),r]}),(s==null?void 0:s.busy)&&!r&&e.jsx("p",{className:"small muted",role:"status",children:"Draken is updating a sync. Open its card to follow progress."}),(s==null?void 0:s.active_call)&&e.jsx("p",{className:"small muted",children:"A call is active. End it before starting another sync."}),l&&e.jsx("div",{className:"alert error",role:"alert",children:l}),e.jsx(xs,{firstRun:!!(s&&!s.syncs.length),onReady:c,onTextReady:f}),e.jsxs("section",{className:"sync-feed","aria-label":"Sync history",children:[s==null?void 0:s.syncs.map(p=>e.jsxs("a",{className:"card sync-tile",href:`/syncs/${p.id}`,onClick:N=>ue(N,t,`/syncs/${p.id}`),children:[e.jsxs("div",{className:"sync-tile-heading",children:[e.jsxs("strong",{children:["Sync #",p.id]}),e.jsx("span",{className:`status ${p.status}`,children:p.busy?"working":p.active_call?"in call":p.needs_retry?"needs retry":p.status==="completed"?"reviewed":p.status==="open"?"open":"discarded"}),e.jsx(es,{size:17,"aria-hidden":"true"})]}),e.jsxs("div",{className:"small muted",children:[mt(p.created_at)," · ",p.item_count," ",p.item_count===1?"entry":"entries"," · ",p.calls," ",p.calls===1?"call":"calls",p.aggregation_cost&&e.jsxs(e.Fragment,{children:[" · ",e.jsx(fs,{cost:p.aggregation_cost})]})]}),e.jsx("p",{className:"sync-tile-preview",children:p.preview||(p.needs_retry?"Preparation stopped. Open this sync to retry; its entries and cached work are retained.":p.busy?"Bringing the new activity together. Open this sync to follow preparation.":"No recap yet. Open this sync to continue the conversation.")}),e.jsx("span",{className:"sync-tile-kind small muted",children:p.preview_kind==="recap"?"Conversation recap · not saved decisions":p.preview_kind==="previous_recap"?"Earlier recap · conversation changed":p.preview_kind==="briefing"?"Briefing preview":"Frozen snapshot"})]},p.id)),s&&!s.syncs.length&&e.jsxs("div",{className:"card welcome",children:[e.jsx("h2",{children:"Your next conversation starts here."}),e.jsx("p",{children:"Draken keeps track of the work you’ve already brought into a sync. Start above; the details can wait until you need them."})]})]}),(s==null?void 0:s.next_cursor)&&e.jsx("button",{className:"btn btn-secondary",onClick:async()=>{try{const p=await Ge(s.next_cursor);n(N=>N?{...N,syncs:[...N.syncs,...p.syncs.filter(m=>!N.syncs.some(y=>y.id===m.id))],next_cursor:p.next_cursor}:p)}catch(p){a(p instanceof Error?p.message:"Could not load history")}},children:"Older syncs"})]})}const ft={scanning:"Checking history for changes…",downloading:"Downloading the local search model…",loading:"Preparing the local search model…",indexing:"Indexing new and changed history…",searching:"Finding matching history…",reading:"Reading a historical source…"},Ve=t=>t<60?`${Math.ceil(t)} sec`:`${Math.ceil(t/60)} min`,$e=t=>t.toLocaleString();function ze({enabled:t,waiting:s=!1,backgroundOnly:n=!1,onLookupChange:r}){const[i,l]=o.useState(null),[a,g]=o.useState(!1);if(o.useEffect(()=>{if(r==null||r(!1),!t)return;l(null),g(!1);const b=new AbortController;let x;const _=async()=>{try{const T=await ct(b.signal);b.signal.aborted||(l(T),g(!1),r==null||r(!!(T.active&&!T.background&&T.work&&["scanning","searching","reading"].includes(T.work.stage)&&T.updated_at&&Math.abs(Date.now()-T.updated_at)<5e3)))}catch{b.signal.aborted||(g(!0),r==null||r(!1))}b.signal.aborted||(x=setTimeout(()=>void _(),1e3))};return _(),()=>{b.abort(),clearTimeout(x),r==null||r(!1)}},[t,r]),!t)return null;if(!(i!=null&&i.active)||!i.work||n&&!i.background)return s?e.jsx("p",{className:"small muted",role:"status",children:a?"Progress is unavailable; your search is still pending.":"Waiting for local history work…"}):null;const d=i.work,S=d.stage==="indexing",c=d.stage==="downloading",j=c?d.downloaded_bytes:d.completed,f=c?d.download_total_bytes:d.total,w=f?Math.floor(j/f*100):0,v=i.updated_at?Math.floor((Date.now()-i.updated_at)/1e3):0;return e.jsxs("section",{className:"history-progress","aria-label":"Local history progress",children:[e.jsx("p",{role:"status",children:e.jsx("strong",{children:S&&!f?"History is up to date.":ft[d.stage]})}),(S&&f>0||c)&&e.jsxs(e.Fragment,{children:[e.jsx("progress",{"aria-label":c?"Model download":"History indexing",max:f||1,value:f?j:void 0}),e.jsxs("p",{children:[c?`${(j/1e6).toFixed(1)} / ${(f/1e6).toFixed(1)} MB`:`${$e(j)} / ${$e(f)} new or changed passages ready`," · ",w,"%"]})]}),e.jsxs("p",{className:"small muted",children:[S&&`${$e(d.reused)} unchanged passages reused (not part of this progress). `,"Elapsed ",Ve(i.elapsed_ms/1e3),".",S&&d.remaining_seconds!==null&&d.remaining_seconds>0&&` About ${Ve(d.remaining_seconds)} remaining (estimate).`,S&&f>0&&d.parallelism&&` Up to ${d.parallelism.workers} embedding worker${d.parallelism.workers===1?"":"s"}, ${d.parallelism.threads} CPU threads total.`,i.queued>0&&` ${$e(i.queued)} other history request${i.queued===1?"":"s"} waiting.`]}),(a||v>=15)&&e.jsxs("p",{className:"small muted",children:[a?"Progress updates are temporarily unavailable.":`No new progress for ${Ve(v)}.`," Cancelling keeps completed embeddings for the next request."]})]})}const xt=t=>t?new Date(t).toLocaleString():"Edit date not retained";function Qe({record:t}){return e.jsxs(e.Fragment,{children:[e.jsxs("p",{className:"small muted",children:[xt(t.at)," · ",t.role," · ",t.kind,t.sync_id?` · Sync #${t.sync_id}`:""]}),e.jsx("p",{className:"small muted",children:t.qualification})]})}function ys({reference:t}){const[s,n]=o.useState(null),[r,i]=o.useState(0),[l,a]=o.useState("");return o.useEffect(()=>{i(0)},[t]),o.useEffect(()=>{let g=!0;return a(""),n(null),dt(t,r).then(d=>{g&&n(d)}).catch(d=>{g&&a(d.message)}),()=>{g=!1}},[t,r]),e.jsxs("section",{className:"history-source","aria-label":"Historical source",children:[l&&e.jsx("p",{role:"alert",children:l}),!s&&!l&&e.jsx("p",{role:"status",children:"Reading historical source…"}),s&&e.jsxs(e.Fragment,{children:[e.jsx("h2",{children:s.record.title}),e.jsx(Qe,{record:s.record}),s.record.workspace&&e.jsx("p",{className:"source-path",children:s.record.workspace}),e.jsx("pre",{className:"history-excerpt",children:s.record.text}),e.jsxs("p",{className:"small muted",children:["Characters ",Math.min(r+1,s.total),"–",Math.min(r+4e3,s.total)," of ",s.total," in the retained record. Source logs may contain more."]}),s.total>4e3&&e.jsxs("div",{className:"pagination",children:[e.jsx("button",{className:"btn btn-secondary",disabled:!r,onClick:()=>i(Math.max(0,r-4e3)),children:"Earlier text"}),e.jsx("button",{className:"btn btn-secondary",disabled:r+4e3>=s.total,onClick:()=>i(r+4e3),children:"Later text"})]}),s.record.sync_id&&e.jsxs("p",{children:[e.jsxs("a",{href:`/syncs/${s.record.sync_id}`,target:"_blank",rel:"noopener noreferrer",children:["Open original sync #",s.record.sync_id]}),s.record.origin_ref&&` · original reference ${s.record.origin_ref}`]}),s.neighbors.length>0&&e.jsxs("details",{children:[e.jsx("summary",{children:"Surrounding retained records"}),e.jsx("p",{className:"small muted",children:"Nearby records in this session or discussion—not necessarily the full conversation."}),s.neighbors.map(g=>e.jsxs("article",{children:[e.jsx("h3",{children:e.jsx("a",{href:`/history/${g.ref}`,target:"_blank",rel:"noopener noreferrer",children:g.title})}),e.jsx(Qe,{record:g}),e.jsx("pre",{className:"history-excerpt",children:g.text})]},g.ref))]})]})]})}function yt({navigate:t,reference:s}){const[n,r]=o.useState(null),[i,l]=o.useState(""),[a,g]=o.useState(""),[d,S]=o.useState(!1),c=o.useRef();return o.useEffect(()=>()=>{var j;return(j=c.current)==null?void 0:j.abort()},[]),e.jsxs("main",{className:"sync-home history-page",children:[e.jsx("a",{className:"back-link",href:"/",onClick:j=>ue(j,t,"/"),children:"All syncs"}),e.jsx("h1",{children:s?"Historical source":"Find earlier work."}),e.jsx("p",{className:"muted",children:"Search retained sessions, sync discussions and explicitly saved notes. Results are historical evidence—not new progress, agreement or proof of execution."}),s?e.jsxs(e.Fragment,{children:[e.jsx(ys,{reference:s},s),e.jsx("p",{children:e.jsx("a",{href:"/history",onClick:j=>ue(j,t,"/history"),children:"Search history"})})]}):e.jsxs(e.Fragment,{children:[e.jsx("p",{className:"small muted",children:"Draken combines meaning and keyword matches automatically. First use prepares a local model (about 136 MB); later searches reuse it and update changed records. Search text stays on this server. Your source exclusions and history baseline still apply."}),e.jsxs("form",{className:"history-search",onSubmit:async j=>{j.preventDefault(),S(!0),g(""),r(null);const f=new AbortController;c.current=f;try{const w=await lt({question:i},f.signal);f.signal.aborted||r(w)}catch(w){f.signal.aborted||g(w instanceof Error?w.message:"Search failed")}finally{S(!1)}},children:[e.jsx("label",{htmlFor:"history-question",children:"What do you want to find?"}),e.jsx("textarea",{id:"history-question",rows:3,maxLength:2e3,value:i,onChange:j=>l(j.target.value),placeholder:"Why did we change that approach?"}),e.jsxs("div",{className:"history-actions",children:[e.jsx("button",{className:"btn btn-primary",disabled:d||!i.trim(),children:d?"Searching…":"Search history"}),d&&e.jsx("button",{type:"button",className:"btn btn-secondary",onClick:()=>{var j;return(j=c.current)==null?void 0:j.abort()},children:"Cancel search"})]}),e.jsx(ze,{enabled:d,waiting:!0})]}),a&&e.jsx("p",{className:"alert error",role:"alert",children:a}),n&&e.jsxs("section",{"aria-label":"History search results",children:[e.jsx("p",{className:"small muted",children:"Meaning + keyword matches"}),!n.results.length&&e.jsx("p",{children:"No matches in this search. That does not prove the event never happened; try different wording or a wider scope."}),n.results.map(j=>e.jsxs("article",{className:"card history-result",children:[e.jsx("h2",{children:e.jsx("a",{href:`/history/${j.ref}`,target:"_blank",rel:"noopener noreferrer",children:j.title})}),e.jsx(Qe,{record:j}),e.jsx("pre",{className:"history-excerpt",children:j.text}),e.jsx("a",{href:`/history/${j.ref}`,target:"_blank",rel:"noopener noreferrer",children:"Read source and surrounding context"})]},j.ref)),e.jsx("p",{className:"small muted",children:n.limitations})]})]})]})}const rs=["[Thinking...]","[Hmmm...]","[Hmmmmmm...]"],is=["[Checking...]","[Looking that up...]"];function Be(t){const s=Array.from(t.trim().replace(/\s+/g," "));if(s.length<=140)return s.join("");const n=s.slice(-140).join(""),r=n.indexOf(" ");return"…"+(r>=0&&r<25?n.slice(r+1):n)}function vt({call:t,historyLookup:s}){const[n,r]=o.useState(0),i=!!t.replyPendingSince&&!["connecting","hearing","speaking","paused","ended"].includes(t.phase)&&!t.error;o.useEffect(()=>{if(r(0),!i)return;const g=setInterval(()=>r(d=>(d+1)%6),5e3);return()=>clearInterval(g)},[i,t.replyPendingSince,s]);let l,a="";return t.phase==="ended"?l="[Call ended]":t.error?l="[Reply unavailable]":t.phase==="paused"?l="[Sound paused]":t.phase==="connecting"?l=t.notice.includes("microphone permission")?"[Waiting for microphone...]":"[Connecting...]":t.phase==="hearing"?(l=t.question?Be(t.question):"[Listening...]",a=t.question?"You":""):i?l=s?is[n%is.length]:rs[n%rs.length]:t.notice.startsWith("Reply muted locally;")?l="[Reply stopped]":t.answer?(l=Be(t.answer),a="Draken"):t.question?(l=Be(t.question),a="You"):l=t.phase==="speaking"?"[Speaking...]":t.muted?"[Microphone off]":"[Listening...]",e.jsxs("div",{className:"voice-captions",role:"region","aria-label":"Live captions","aria-live":"off","data-kind":a?"transcript":"status",children:[a&&e.jsx("span",{className:"voice-caption-speaker",children:a}),e.jsx("div",{className:"voice-caption-window",children:e.jsx("p",{children:l})})]})}var Y,U,Q,de,xe,we,ne,ie,J,he,Te,V,Ae,Pe,ye,be,_e,Ie;class jt{constructor({onClose:s=()=>{},onEvent:n=()=>{}}={}){z(this,Y);z(this,U);z(this,Q);z(this,de);z(this,xe,new Set);z(this,we,[]);z(this,ne);z(this,ie);z(this,J);z(this,he,new Float32Array(1024));z(this,Te,new AbortController);z(this,V,!1);z(this,Ae,!1);z(this,Pe,!1);z(this,ye);z(this,be);z(this,_e);z(this,Ie);q(this,_e,s),q(this,Ie,n)}get closed(){return u(this,V)}get clock(){var s;return!u(this,V)&&((s=u(this,U))==null?void 0:s.state)==="running"?u(this,U).currentTime:NaN}get audioState(){var s;return((s=u(this,U))==null?void 0:s.state)||"closed"}async resume(){var s,n;u(this,V)||(await((s=u(this,U))==null?void 0:s.resume()),await((n=u(this,J))==null?void 0:n.play()))}gateInput(s){var n;(n=u(this,Q))==null||n.getAudioTracks().forEach(r=>{r.enabled=!!s})}get inputActive(){var s;return!!((s=u(this,Q))!=null&&s.getAudioTracks().some(n=>n.readyState==="live"))}get level(){var n;if(u(this,V)||u(this,Pe)||((n=u(this,U))==null?void 0:n.state)!=="running"||!u(this,ne))return 0;u(this,ne).getFloatTimeDomainData(u(this,he));const s=Math.sqrt(u(this,he).reduce((r,i)=>r+i*i,0)/u(this,he).length);return Number.isFinite(s)?Math.min(1,s*12):0}async open(s,n){if(u(this,Ae)||u(this,V))throw s.getTracks().forEach(r=>r.stop()),new Error("A voice peer can open only once.");q(this,Ae,!0),q(this,Q,s);try{if(s.getAudioTracks().length!==1||s.getVideoTracks().length)throw new Error("Exactly one audio track is required.");if(q(this,Y,new RTCPeerConnection),q(this,U,new AudioContext),q(this,ne,u(this,U).createAnalyser()),u(this,ne).fftSize=u(this,he).length,q(this,ie,u(this,U).createGain()),u(this,ne).connect(u(this,ie)),u(this,ie).connect(u(this,U).destination),q(this,be,setTimeout(()=>this.close("Voice connection timed out."),6e4)),await u(this,U).resume(),u(this,V)||u(this,U).state!=="running")throw new Error("Voice playback could not start.");q(this,de,u(this,Y).addTrack(s.getAudioTracks()[0],s));const r=u(this,Y).createDataChannel("oai-events"),i=new Promise((a,g)=>{q(this,ye,g);const d=()=>{u(this,Y).connectionState==="connected"&&r.readyState==="open"?(q(this,ye,void 0),clearTimeout(u(this,be)),a()):["failed","disconnected","closed"].includes(u(this,Y).connectionState)&&this.close("Voice connection lost. Start a new call explicitly.")};u(this,Y).onconnectionstatechange=d,r.onopen=d,r.onclose=()=>this.close("Voice event connection closed."),r.onerror=()=>this.close("Voice event connection failed.")});if(i.catch(()=>{}),r.onmessage=a=>{if(!u(this,V)){if(typeof a.data!="string"||a.data.length>2e5){this.close("Voice event exceeds its limit.");return}try{u(this,Ie).call(this,JSON.parse(a.data))}catch{this.close("Invalid voice event.")}}},u(this,Y).ontrack=a=>{if(u(this,V)){a.track.stop();return}if(a.track.kind!=="audio"||u(this,xe).size){this.close("Unexpected remote media track.");return}u(this,xe).add(a.track);const g=new MediaStream([a.track]);q(this,J,new Audio),u(this,J).muted=!0,u(this,J).srcObject=g,u(this,J).play().catch(()=>this.close("Voice playback could not start."));const d=u(this,U).createMediaStreamSource(g);u(this,we).push(d),d.connect(u(this,ne)),a.track.onended=()=>this.close("Voice output ended.")},await u(this,Y).setLocalDescription(await u(this,Y).createOffer()),u(this,V))throw new Error("Voice connection cancelled.");const l=await n(u(this,Y).localDescription.sdp,u(this,Te).signal);if(u(this,V))throw new Error("Voice connection cancelled.");if(typeof l!="string"||l.length>64e3||!l.startsWith("v=0"))throw new Error("Invalid voice answer.");await u(this,Y).setRemoteDescription({type:"answer",sdp:l}),await i}catch(r){throw this.close("Voice connection failed or cancelled."),r}}muteOutput(s){q(this,Pe,!!s),u(this,ie)&&(u(this,ie).gain.value=s?0:1)}stopInput(){var s;(s=u(this,Q))==null||s.getTracks().forEach(n=>n.stop()),q(this,Q,void 0),u(this,de)&&!u(this,V)&&u(this,de).replaceTrack(null).catch(()=>this.close("Cannot mute voice input."))}async replaceInput(s){if(u(this,V)||!u(this,de)||s.getAudioTracks().length!==1||s.getVideoTracks().length)throw s.getTracks().forEach(r=>r.stop()),new Error("Cannot attach voice input.");const n=u(this,Q);q(this,Q,s),n==null||n.getTracks().forEach(r=>r.stop());try{await u(this,de).replaceTrack(s.getAudioTracks()[0])}catch(r){throw s.getTracks().forEach(i=>i.stop()),this.close("Cannot attach voice input."),r}if(u(this,V)||u(this,Q)!==s)throw s.getTracks().forEach(r=>r.stop()),new Error("Voice input was superseded.")}close(s="Call ended."){var n,r,i,l,a;if(!u(this,V)){q(this,V,!0),clearTimeout(u(this,be)),u(this,Te).abort(),(n=u(this,ye))==null||n.call(this,new Error(s)),q(this,ye,void 0),(r=u(this,Y))==null||r.close(),(i=u(this,Q))==null||i.getTracks().forEach(g=>g.stop()),u(this,xe).forEach(g=>g.stop()),u(this,xe).clear(),u(this,we).forEach(g=>g.disconnect()),q(this,we,[]),(l=u(this,ne))==null||l.disconnect(),(a=u(this,ie))==null||a.disconnect(),u(this,he).fill(0),u(this,J)&&(u(this,J).pause(),u(this,J).srcObject=null,q(this,J,void 0)),u(this,U)&&u(this,U).state!=="closed"&&u(this,U).close().catch(()=>{});try{u(this,_e).call(this,s)}catch{}}}}Y=new WeakMap,U=new WeakMap,Q=new WeakMap,de=new WeakMap,xe=new WeakMap,we=new WeakMap,ne=new WeakMap,ie=new WeakMap,J=new WeakMap,he=new WeakMap,Te=new WeakMap,V=new WeakMap,Ae=new WeakMap,Pe=new WeakMap,ye=new WeakMap,be=new WeakMap,_e=new WeakMap,Ie=new WeakMap;class wt{constructor(s){A(this,"state",{...We,phase:"connecting"});A(this,"alive",!0);A(this,"id","");A(this,"pageExit",()=>{this.end()});A(this,"peer");A(this,"life",new AbortController);A(this,"inputContext",new AudioContext);A(this,"inputMeter",this.inputContext.createAnalyser());A(this,"inputSource");A(this,"input");A(this,"changing",!1);A(this,"cursor",0);A(this,"timer",0);A(this,"speechAt",0);A(this,"providerDone",!0);A(this,"stopped",!1);A(this,"newQuestion",!1);A(this,"pendingAnswer",!1);A(this,"answerSettled",!1);A(this,"awaitingUser",!1);A(this,"userId",0);A(this,"inputEpoch",0);A(this,"pendingNotice","Preparing the answer. I’ll continue automatically.");A(this,"assistantId",null);A(this,"observed",0);A(this,"reportedAt",0);A(this,"micBuffer",new Float32Array(1024));this.options=s,window.addEventListener("pagehide",this.pageExit),this.inputMeter.fftSize=1024,this.inputContext.resume().catch(()=>{}),this.peer=new jt({onEvent:n=>this.providerEvent(n),onClose:n=>{this.alive&&(this.set({error:n}),this.end())}}),this.set({})}set(s){this.state={...this.state,...s},this.options.onState(this.state)}async request(s,n){return Z(`/live/calls/${this.id}${s}`,{method:n?"POST":"GET",...n?{body:JSON.stringify(n)}:{},signal:this.life.signal})}async microphone(){var n;const s=await navigator.mediaDevices.getUserMedia({audio:{echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0},video:!1});if(!this.alive)throw s.getTracks().forEach(r=>r.stop()),new Error("Call ended");(n=this.inputSource)==null||n.disconnect(),this.inputSource=this.inputContext.createMediaStreamSource(s),this.inputSource.connect(this.inputMeter),this.input=s,this.set({microphone:!0});for(const r of s.getAudioTracks())r.addEventListener("ended",()=>{this.alive&&!this.state.muted&&this.input===s&&(this.set({muted:!0,microphone:!1,notice:"Microphone disconnected. Type, or turn the microphone on again."}),this.peer.stopInput())});return s}silentInput(){const s=this.inputContext.createMediaStreamDestination(),n=this.inputContext.createConstantSource();return n.offset.value=0,n.connect(s),n.start(),s.stream}async start(s,n){var r,i;try{if(await(n==null?void 0:n()),!this.alive)return;this.set({notice:"Connecting your call. Your microphone is still off."}),this.id=crypto.randomUUID();const l=await Z("/live/calls",{method:"POST",body:JSON.stringify({syncId:s,requestId:this.id}),signal:this.life.signal});if(l.id!==this.id)throw new Error("The call reservation identity did not match.");if(!this.alive){Z(`/live/calls/${this.id}/end`,{method:"POST",keepalive:!0}).catch(()=>{});return}if(document.visibilityState!=="visible")throw new Error("History is ready. Return to this page and start the call again to enable the microphone.");this.set({historyReady:!0,startedAt:l.startedAt,notice:"History is ready. Waiting for microphone permission…"}),this.poll();let a;try{a=await this.microphone(),this.set({notice:""})}catch{if(!this.alive)return;a=this.silentInput(),this.set({muted:!0,notice:"Microphone unavailable. You can type instead."})}if(this.input=a,await this.peer.open(a,async(g,d)=>(await Z(`/live/calls/${l.id}/connect`,{method:"POST",body:JSON.stringify({sdp:g}),signal:d})).sdp),!this.alive)return;try{(i=(r=this.options).onPlayback)==null||i.call(r,{text:"",samples:new Float32Array(0),sampleRate:0,duration:1/0,startedAt:0,now:()=>this.peer.clock,level:()=>this.peer.level})}catch{}this.set({phase:this.state.replyPendingSince?"thinking":"listening"}),this.timer=window.setInterval(()=>this.meter(),80)}catch(l){this.alive&&(this.set({error:l instanceof Error?l.message:"Live voice could not start"}),await this.end())}}providerEvent(s){var n,r;this.alive&&(s.type==="input_transcript.added"&&this.stopped&&this.newQuestion&&(this.stopped=!1,this.peer.muteOutput(!1),this.set({notice:""})),s.type==="turn.created"&&((n=s.turn)==null?void 0:n.role)==="assistant"&&(this.stopped&&this.newQuestion&&(this.stopped=!1,this.newQuestion=!1,this.peer.muteOutput(!1)),this.providerDone=!1),s.type==="output_transcript.added"&&!this.stopped&&(this.providerDone=!1,this.state.voiceInterruption||this.peer.gateInput(!1)),s.type==="turn.done"&&((r=s.turn)==null?void 0:r.role)==="assistant"&&(this.providerDone=!0))}meter(){var i,l;if(!this.alive)return;const s=performance.now(),n=this.peer.level;let r=0;this.state.muted||(this.inputMeter.getFloatTimeDomainData(this.micBuffer),r=Math.sqrt(this.micBuffer.reduce((a,g)=>a+g*g,0)/this.micBuffer.length)*10),this.stopped&&r>.08&&(this.newQuestion=!0),(l=(i=this.options).onLevel)==null||l.call(i,Math.min(1,Math.max(n,r))),n>.02?(this.speechAt=s,this.observed+=80,this.state.phase!=="speaking"&&this.set({phase:"speaking"}),this.state.voiceInterruption||this.peer.gateInput(!1),this.assistantId&&s-this.reportedAt>1e3&&(this.reportedAt=s,this.request("/observed",{messageId:this.assistantId,milliseconds:this.observed}).catch(()=>{}))):(this.providerDone||this.pendingAnswer||this.answerSettled)&&s-this.speechAt>400&&this.state.phase==="speaking"&&(this.set({phase:this.state.replyPendingSince?"thinking":"listening"}),this.peer.gateInput(!this.state.muted)),this.peer.audioState==="suspended"&&this.state.phase!=="paused"&&this.set({phase:"paused"})}async poll(){var s,n;try{for(;this.alive;){const r=await this.request(`/events?after=${this.cursor}`);if(!this.alive)return;for(const i of r.events){if(this.cursor=i.sequence,i.type==="sources"&&this.set({evidence:i.evidence}),i.type==="message"){if(i.role==="user"){if(i.id<this.userId)continue;i.id>this.userId&&(this.awaitingUser||this.inputEpoch++,this.pendingAnswer=!1,this.answerSettled=!1,this.set({answer:"",error:"",replyPendingSince:this.awaitingUser?this.state.replyPendingSince:0,...!this.awaitingUser&&!this.stopped?{phase:"hearing"}:{},...this.state.notice===this.pendingNotice?{notice:""}:{}}),this.awaitingUser=!1),this.userId=i.id,this.set({question:i.text}),i.final&&!this.answerSettled&&(!this.stopped||this.newQuestion)&&(this.pendingAnswer=!0,this.set({replyPendingSince:this.state.replyPendingSince||Date.now(),...["speaking","paused"].includes(this.state.phase)?{}:{phase:"thinking"}}))}else this.assistantId!==i.id&&(this.assistantId=i.id,this.observed=0),this.set({turnId:i.id,answer:i.text,evidence:i.evidence});(n=(s=this.options).onTurn)==null||n.call(s,i.role==="user"?i.text:"",i.role==="assistant"?i.text:"",i.evidence,i.id)}i.type==="answer_pending"&&i.id===this.userId&&!this.awaitingUser&&(!this.stopped||this.newQuestion)&&(this.pendingAnswer=i.pending===!0,this.answerSettled=!this.pendingAnswer,this.set({replyPendingSince:this.pendingAnswer?this.state.replyPendingSince||Date.now():0,...["thinking","listening","hearing"].includes(this.state.phase)?{phase:this.pendingAnswer?"thinking":"listening"}:{},...!this.state.notice||this.state.notice===this.pendingNotice?{notice:this.pendingAnswer?this.pendingNotice:""}:{},...i.error?{error:i.error}:{}})),i.type==="error"&&this.set({error:i.error})}if(!r.active){await this.end();return}await new Promise(i=>setTimeout(i,250))}}catch(r){this.alive&&(this.set({error:r instanceof Error?r.message:"Live connection lost"}),await this.end())}}async sendText(s){if(!this.alive||!this.id||!s.trim()||s.length>2e3)return;const n=++this.inputEpoch;this.newQuestion=!0,this.awaitingUser=!0,this.answerSettled=!1,this.pendingAnswer=!1,this.set({phase:"thinking",error:"",question:s,answer:"",replyPendingSince:Date.now()});try{await this.request("/text",{question:s,requestId:crypto.randomUUID()}),this.alive&&n===this.inputEpoch&&this.stopped&&(this.stopped=!1,this.peer.muteOutput(!1),this.set({notice:""}))}catch(r){this.alive&&n===this.inputEpoch&&(this.awaitingUser=!1,this.pendingAnswer=!1,this.answerSettled=!0,this.set({phase:"listening",replyPendingSince:0,error:r instanceof Error?r.message:"Question could not be sent"}))}}async toggleMute(){var s;if(!(!this.alive||this.changing)){this.changing=!0;try{if(!this.state.muted)this.set({muted:!0}),this.peer.stopInput(),(s=this.inputSource)==null||s.disconnect();else{const n=await this.microphone();await this.peer.replaceInput(n),this.alive&&(this.set({muted:!1,notice:""}),this.peer.gateInput(this.state.voiceInterruption||this.state.phase!=="speaking"))}}catch{this.alive&&this.set({muted:!0,notice:"Microphone unavailable. You can type instead."})}finally{this.changing=!1}}}setVoiceInterruption(s){this.set({voiceInterruption:s}),this.peer.gateInput(!this.state.muted&&(s||this.state.phase!=="speaking"))}async interrupt(){if(this.alive){this.inputEpoch++,this.pendingAnswer=!1,this.awaitingUser=!1,this.answerSettled=!0,this.stopped=!0,this.newQuestion=!1,this.peer.muteOutput(!0),this.peer.gateInput(!this.state.muted),this.set({phase:"listening",replyPendingSince:0,notice:"Reply muted locally; a stop request was sent. Ask another question to continue."});try{await this.request("/interrupt",{})}catch{this.alive&&(this.set({error:"The remote stop could not be confirmed. The call was ended."}),await this.end())}}}async resumeSound(){await this.peer.resume(),this.alive&&this.set({phase:this.state.replyPendingSince?"thinking":"listening"})}async end(){var s,n,r,i,l,a;if(this.alive){this.alive=!1,window.removeEventListener("pagehide",this.pageExit),clearInterval(this.timer),this.life.abort(),(s=this.input)==null||s.getTracks().forEach(g=>g.stop()),(n=this.inputSource)==null||n.disconnect(),this.peer.close(),this.inputContext.close().catch(()=>{});try{(i=(r=this.options).onPlayback)==null||i.call(r,null)}catch{}if(this.pendingAnswer=!1,this.awaitingUser=!1,(a=(l=this.options).onLevel)==null||a.call(l,0),this.set({phase:"ended",muted:!0,notice:"",replyPendingSince:0}),this.id){const g=new AbortController,d=setTimeout(()=>g.abort(),4e3);try{await Z(`/live/calls/${this.id}/end`,{method:"POST",keepalive:!0,signal:g.signal})}catch{}finally{clearTimeout(d)}}}}}const bt={connecting:"Getting ready",listening:"Your turn",hearing:"Listening to you",thinking:"Preparing your answer",speaking:"Draken is speaking",paused:"Sound paused",ended:"Call ended"},kt=t=>`${Math.floor(t/60)}:${String(t%60).padStart(2,"0")}`;function Nt({sync:t,readiness:s,onPrepareHistory:n,disabled:r,beforeStart:i,onActiveChange:l,onClosed:a,onChat:g,autoStart:d=!1,onAutoStartHandled:S}){const[c,j]=o.useState(null),[f,w]=o.useState(""),[v,b]=o.useState(!1),[x,_]=o.useState(We),[T,p]=o.useState(0),[N,m]=o.useState(!1),[y,E]=o.useState(""),[F,X]=o.useState([]),[I,R]=o.useState(null),[L,oe]=o.useState(""),[ae,B]=o.useState(!1),[ee,pe]=o.useState(!1),K=o.useRef(null),me=o.useRef(null),ge=o.useRef(null),De=o.useRef(null),H=o.useRef(null),G=o.useRef(!0),ce=o.useRef(!1),re=o.useRef(!1),[ve,ke]=o.useState(!1),Ne=[...t.items,...t.context],le=Ne.find(h=>h.ref===L),se=(s==null?void 0:s.ready)===!0,fe=window.isSecureContext,je=new URL(window.location.href);je.protocol="https:",je.port=String((c==null?void 0:c.httpsPort)||443),o.useEffect(()=>{L&&me.current&&ge.current&&(me.current.scrollTop+=ge.current.getBoundingClientRect().top-me.current.getBoundingClientRect().top)},[L]);const k=async()=>{try{const h=await Z("/status");G.current&&(j(h),w(""))}catch(h){G.current&&w(h instanceof Error?h.message:"Could not check ChatGPT voice")}};o.useEffect(()=>{G.current=!0,k();const h=setInterval(()=>{H.current||k()},15e3);return()=>{var C;clearInterval(h),G.current=!1,(C=H.current)==null||C.end()}},[]),o.useEffect(()=>{var h,C,D;v&&!((h=K.current)!=null&&h.open)?(C=K.current)==null||C.showModal():v||(D=K.current)==null||D.close()},[v]),o.useEffect(()=>{if(!v||!x.startedAt||x.phase==="ended")return;const h=()=>p(Math.max(0,Math.floor((Date.now()-x.startedAt)/1e3)));h();const C=setInterval(h,1e3);return()=>clearInterval(C)},[v,x.startedAt,x.phase==="ended"]);const O=async()=>{var h;if(!(H.current||ce.current||re.current||!se)){re.current=!0,ke(!0),w("");try{if(await i(),!G.current||document.visibilityState!=="visible")return;_({...We}),p(0),X([]),E(""),oe(""),m(!1),B(!1),pe(!1),b(!0),l(!0);const C=new wt({onState:D=>{G.current&&(_(D),!D.microphone&&D.muted&&m(!0))},onLevel:()=>{},onPlayback:D=>{De.current=D},onTurn:(D,Me,Je,qe)=>{G.current&&X(He=>He.some(Re=>Re.id===qe)?He.map(Re=>Re.id===qe?{id:qe,question:D,answer:Me,refs:Je}:Re):[...He,{id:qe,question:D,answer:Me,refs:Je}])}});H.current=C,H.current===C&&await C.start(t.id)}catch(C){if(await((h=H.current)==null?void 0:h.end()),G.current){const D=C instanceof Error?C.message:"The call could not start";w(D),H.current&&_(Me=>({...Me,phase:"ended",error:D}))}}finally{re.current=!1,G.current&&ke(!1)}}};o.useEffect(()=>{!d||r||!se||!c||(S==null||S(),c.installed&&!c.activeCall&&fe&&document.visibilityState==="visible"?O():w("Your snapshot is ready. Start the call explicitly when audio is available and this page is visible."))},[d,r,se,c]);const $=async()=>{var h;if(!ce.current){ce.current=!0,await((h=H.current)==null?void 0:h.end()),H.current=null,G.current&&(b(!1),R(null),l(!1));try{await a(),await k()}finally{ce.current=!1}}},W=async()=>{try{R(await Z(`/syncs/${t.id}/history`))}catch(h){w(h instanceof Error?h.message:"Could not load call history")}},te=async()=>{try{const h=await fetch("/api/voice/certificate",{headers:gs(!1)});if(!h.ok)throw new Error("Could not download the local certificate. Check your dashboard login.");const C=URL.createObjectURL(await h.blob()),D=document.createElement("a");D.href=C,D.download="draken-local-root.crt",D.click(),setTimeout(()=>URL.revokeObjectURL(C),1e3)}catch(h){w(h instanceof Error?h.message:"Certificate download failed")}},Fe=()=>{var C;if(!y.trim())return;const h=y.trim();E(""),(C=H.current)==null||C.sendText(h)};return e.jsxs(e.Fragment,{children:[e.jsxs("section",{className:"card voice-entry","aria-label":"Voice calls",children:[e.jsxs("div",{className:"voice-entry-main",children:[e.jsx("div",{className:"voice-entry-icon","aria-hidden":"true",children:e.jsx(Ye,{size:22})}),e.jsxs("div",{children:[e.jsx("h2",{children:"Talk it through. Out loud."}),e.jsx("p",{className:"muted small",children:"Live voice through ChatGPT. Audio goes to OpenAI; replies may paraphrase."})]}),e.jsxs("div",{className:"conversation-actions",children:[e.jsxs("button",{className:"btn btn-secondary",disabled:v||ve,onClick:g,children:[e.jsx(ds,{size:16}),"Chat instead"]}),!fe&&(c!=null&&c.httpsPort)?e.jsxs("a",{className:"btn btn-primary",href:je.href,children:["Open secure call page ",e.jsx(_s,{size:15})]}):e.jsxs("button",{className:"btn btn-primary",disabled:r||ve||!se||!(c!=null&&c.installed)||!!(c!=null&&c.activeCall)||!fe,onClick:()=>void O(),children:[e.jsx(Ye,{size:16}),"Call Draken"]})]})]}),e.jsx("p",{className:"small muted",children:"Relevant earlier history is found automatically. Retrieved excerpts go to ChatGPT, separately from this frozen snapshot; no review or saved decisions change."}),!fe&&e.jsxs("p",{className:"small muted",children:["The microphone needs trusted HTTPS. ",c!=null&&c.httpsPort?"The secure page uses your existing dashboard login. Install the local certificate once on this device before opening it.":"Use localhost, or enable HTTPS on the server."]}),(c==null?void 0:c.certificateAvailable)&&e.jsxs("details",{className:"voice-history",children:[e.jsx("summary",{children:"First-time browser setup"}),e.jsx("p",{className:"small",children:"Trust only your own Draken server’s certificate. This is a one-time device setup, not another account or voice subscription."}),e.jsx("button",{className:"btn btn-secondary",onClick:()=>void te(),children:"Download local certificate"}),e.jsxs("ul",{className:"small",children:[e.jsxs("li",{children:[e.jsx("strong",{children:"Windows:"})," open the downloaded certificate → Install Certificate → Current User → place in Trusted Root Certification Authorities."]}),e.jsxs("li",{children:[e.jsx("strong",{children:"macOS:"})," import into Keychain Access → login keychain. Open its Trust section and choose Always Trust."]}),e.jsxs("li",{children:[e.jsx("strong",{children:"Firefox/Linux:"})," Settings → Privacy & Security → Certificates → View Certificates → Authorities → Import. Trust it to identify websites."]})]}),e.jsxs("p",{className:"small muted",children:["Restart the browser if needed, open the secure page, sign in, and allow the microphone when you start a call. Keep the server’s private keys private. See ",e.jsx("code",{children:"VOICE.md"})," for an SSH-tunnel alternative."]})]}),t.status==="open"&&e.jsx("p",{className:"small muted",role:"status",children:se?`Ready to call. History cutoff: ${s!=null&&s.before?new Date(s.before).toLocaleString():"prepared snapshot"}. Refresh history for later work.`:s?s.preparing?"Preparing history before calling. Your microphone is off.":s.briefingReady?"History needs preparation before you can call.":"Prepare the briefing first.":"Checking call readiness…"}),t.status==="open"&&(s==null?void 0:s.briefingReady)&&!s.preparing&&e.jsx("button",{className:"btn btn-secondary",disabled:r||ve,onClick:n,children:se?"Refresh history":"Prepare history"}),(s==null?void 0:s.error)&&!se&&e.jsx("p",{className:"small",role:"alert",children:s.error}),t.status!=="open"&&e.jsx("p",{className:"small muted",children:"This sync is closed. Start a new sync for another call."}),c&&!c.installed&&e.jsxs("p",{className:"small muted",children:["ChatGPT voice needs server setup and sign-in: ",e.jsx("code",{children:"npm run voice:realtime:setup"}),", then ",e.jsx("code",{children:"npm run voice:realtime:login"}),"."]}),f&&e.jsxs("p",{className:"small",role:"alert",children:[f," ",e.jsx("button",{className:"btn btn-secondary",onClick:()=>void k(),children:"Retry"})]}),(c==null?void 0:c.activeCall)&&!v&&e.jsxs("div",{className:"small voice-reconnect",children:["A call is still open in another tab or device.",e.jsx("button",{className:"btn btn-secondary",disabled:r,onClick:()=>{window.confirm("End the existing voice call? Its completed transcript is kept.")&&Z(`/live/calls/${c.activeCall.id}/end`,{method:"POST",body:"{}"}).then(k).catch(h=>w(h.message))},children:"End previous call"})]}),e.jsxs("details",{className:"voice-history",onToggle:h=>{h.currentTarget.open&&W()},children:[e.jsx("summary",{children:"Call history"}),(I==null?void 0:I.length)===0&&e.jsx("p",{className:"muted small",children:"No calls yet. Transcripts are saved here; raw audio is not recorded."}),I==null?void 0:I.map(h=>e.jsxs("details",{className:"voice-history-call",children:[e.jsxs("summary",{children:[new Date(h.started_at).toLocaleString()," · ",h.turns.length," ",h.mode==="native"?"messages":"turns"," · ",h.status]}),e.jsx("p",{className:"small muted",children:h.end_reason||"Call in progress"}),h.mode==="native"?e.jsx("p",{className:"small muted",children:"Ordered live transcripts, not verified question–answer pairs. Sources are supplied context, not verified citations. Exact playback is not confirmed."}):e.jsx("p",{className:"small muted",children:"Historical call from the retired local speech engine. These records are preserved; this engine cannot start new calls."}),h.turns.map(C=>e.jsxs("div",{className:"voice-history-turn",children:[C.question&&e.jsxs(e.Fragment,{children:[e.jsx("strong",{className:"message-author",children:"You"}),e.jsx("p",{className:"prose",children:C.question})]}),(C.answer||!C.question||h.mode!=="native")&&e.jsxs(e.Fragment,{children:[e.jsxs("strong",{className:"message-author",children:["Draken · ",C.status]}),e.jsx(Ee,{text:`${C.answer||C.error||"No reply generated."} ${JSON.parse(C.evidence_json).map(D=>`[${D}]`).join(" ")}`,evidence:Ne}),C.status!=="completed"&&e.jsxs("p",{className:"small muted",children:["Generated text is shown above. ",C.heard_text?`Confirmed played: ${C.heard_text}`:"Playback was not confirmed."]})]})]},C.id))]},h.id))]})]}),e.jsxs("dialog",{ref:K,className:"voice-dialog","aria-labelledby":"voice-title",onCancel:h=>{h.preventDefault(),$()},children:[e.jsxs("div",{className:"voice-dialog-header",children:[e.jsxs("div",{children:[e.jsx("span",{className:"eyebrow",children:"DRAKEN / VOICE SYNC"}),e.jsxs("h2",{id:"voice-title",children:["Sync #",t.id]})]}),e.jsx("span",{className:"voice-clock","aria-label":"Call duration",children:kt(T)}),e.jsx("button",{className:"icon-button","aria-label":"Close call",onClick:()=>void $(),children:e.jsx(Ke,{size:18})})]}),e.jsxs("div",{className:"voice-call-body",children:[x.historyReady?e.jsxs("div",{className:"voice-scene",children:[v&&x.phase!=="ended"?e.jsx(ws,{playback:De,mode:x.phase==="speaking"?"speaking":x.phase==="hearing"?"listening":x.replyPendingSince&&!x.error?"thinking":"idle"}):e.jsx("img",{loading:"lazy",className:"voice-scene-poster",src:"/persona/call-poster.webp",alt:"Draken’s workshop"}),e.jsx(vt,{call:x,historyLookup:ee})]}):e.jsxs("section",{className:"voice-preparation","aria-label":"Call preparation",children:[e.jsx("h3",{children:x.phase==="ended"?"Call could not start":"Connecting your call"}),e.jsx("p",{className:"small muted",children:"Your microphone is off until the call is ready."})]}),e.jsx("p",{className:"sr-only",role:"status","aria-label":"Call state","aria-live":"polite",children:x.muted&&x.phase==="listening"?"Microphone muted":bt[x.phase]})]}),x.error&&e.jsx("div",{className:"alert error",role:"alert",children:x.error}),x.error&&x.question&&x.phase==="listening"&&e.jsx("button",{className:"btn btn-primary",onClick:()=>{var h;return void((h=H.current)==null?void 0:h.sendText(x.question))},children:"Retry question"}),x.phase==="paused"&&e.jsx("button",{className:"btn btn-primary",onClick:()=>{var h;return void((h=H.current)==null?void 0:h.resumeSound())},children:"Resume sound"}),e.jsxs("div",{className:"voice-controls",children:[e.jsxs("button",{className:`btn btn-secondary ${x.muted?"is-muted":""}`,disabled:x.phase==="connecting"||x.phase==="ended",onClick:()=>{var h;return void((h=H.current)==null?void 0:h.toggleMute())},children:[x.muted?e.jsx(Ls,{size:18}):e.jsx(Os,{size:18}),x.muted?x.microphone?"Unmute":"Enable mic":"Mute"]}),e.jsxs("button",{className:"btn btn-secondary",disabled:!["thinking","speaking","paused"].includes(x.phase),onClick:()=>{var h;return void((h=H.current)==null?void 0:h.interrupt().catch(()=>{}))},children:[e.jsx(hs,{size:15}),"Stop reply"]}),e.jsxs("button",{className:"btn btn-danger",onClick:()=>void $(),children:[e.jsx($s,{size:18}),x.phase==="ended"?"Close":"End call"]})]}),e.jsxs("div",{className:"voice-options",children:[e.jsxs("button",{className:"voice-keyboard-toggle","aria-pressed":x.voiceInterruption,disabled:x.phase==="connecting"||x.phase==="ended",onClick:()=>{var h;return(h=H.current)==null?void 0:h.setVoiceInterruption(!x.voiceInterruption)},children:[e.jsx(Is,{size:16}),"Headphone mode"]}),e.jsxs("button",{className:"voice-keyboard-toggle",onClick:()=>m(h=>!h),"aria-expanded":N,children:[e.jsx(Ds,{size:16}),N?"Hide keyboard":"Type a question"]})]}),N&&e.jsxs("form",{className:"voice-compose",onSubmit:h=>{h.preventDefault(),Fe()},children:[e.jsx("input",{className:"input","aria-label":"Type a question for this call",placeholder:"Or ask here…",maxLength:2e3,disabled:x.phase==="connecting"||x.phase==="ended",value:y,onChange:h=>E(h.target.value)}),e.jsx("button",{className:"btn btn-primary","aria-label":"Send voice-call question",disabled:!y.trim()||x.phase==="connecting"||x.phase==="ended",children:e.jsx(ls,{size:18})})]}),e.jsxs("details",{className:"voice-conversation",open:ae,onToggle:h=>B(h.currentTarget.open),children:[e.jsx("summary",{children:"Conversation & details"}),e.jsxs("div",{className:"voice-call-details",ref:me,children:[x.notice&&e.jsx("p",{className:"small muted voice-notice",children:x.notice}),e.jsx(ze,{enabled:v&&x.historyReady&&(!!x.replyPendingSince||["connecting","thinking"].includes(x.phase)),onLookupChange:pe}),e.jsx("p",{className:"small muted",children:x.phase==="speaking"?x.voiceInterruption?"Speak to interrupt. Use headphones to avoid speaker feedback.":"Listening pauses during replies to prevent echo. Tap Stop reply to speak.":"Speak naturally. A short pause sends your question."}),e.jsx("div",{className:"voice-transcript",children:F.map(h=>e.jsxs("div",{children:[h.question&&e.jsxs(e.Fragment,{children:[e.jsx("strong",{children:"You"}),e.jsx("p",{children:h.question})]}),h.answer&&e.jsxs(e.Fragment,{children:[e.jsx("strong",{children:"Draken · generated reply"}),e.jsx("p",{className:h.id===x.turnId?"voice-answer":void 0,children:h.answer})]})]},h.id))}),!F.length&&e.jsx("p",{className:"small muted",children:"No transcript yet."}),e.jsx("p",{className:"small muted",children:"Live generated transcripts, not word-timed subtitles. Exact playback and agreement are not confirmed. Full text is retained here even when the scene shows only its latest lines."}),x.evidence.length>0&&e.jsxs("details",{className:"voice-history",children:[e.jsxs("summary",{children:["Sources supplied (",x.evidence.length,")"]}),e.jsx("p",{className:"small muted",children:"Context available to the voice model, not verified citations for every spoken claim."}),e.jsx("div",{className:"voice-sources",children:x.evidence.map(h=>e.jsx("button",{className:"citation",onClick:C=>{const D=C.currentTarget.closest("details");D&&(D.open=!1),oe(L===h?"":h)},children:h.startsWith("H")?`History ${h.slice(-6)}`:`Source ${h}`},h))})]}),/^H[a-f0-9]{24}$/.test(L)&&e.jsxs("section",{className:"voice-source",ref:ge,children:[e.jsx("button",{className:"btn btn-secondary",onClick:()=>oe(""),children:"Close historical source"}),e.jsx(ys,{reference:L})]}),le&&e.jsxs("section",{className:"voice-source",ref:ge,children:[e.jsxs("div",{className:"section-heading",children:[e.jsxs("strong",{children:[le.ref," · ",le.session_name||le.cwd]}),e.jsx("button",{className:"icon-button","aria-label":"Close source",onClick:()=>oe(""),children:e.jsx(Ke,{size:16})})]}),e.jsx("pre",{children:le.text})]})]})]}),e.jsxs("div",{className:"voice-footer",children:[e.jsx(Ts,{size:14}),e.jsx("span",{children:"Experimental live audio to OpenAI · Generated, not verified · 30-minute limit"})]})]})]})}function St({sync:t,readiness:s,draft:n,setDraft:r,disabled:i,sending:l,onSend:a,onCancel:g,onPrepareHistory:d,onVoice:S}){const c=t.tree.run,j=t.status==="open",f=t.busy&&(c==null?void 0:c.status)==="running"&&!!c.question,w=!t.busy&&!!(c!=null&&c.question)&&["failed","cancelled","interrupted"].includes((c==null?void 0:c.status)||""),v=l?n:f||w?c==null?void 0:c.question:null,b=f||l,x=l?"Sending your message…":c!=null&&c.stage.includes("Searching")?"Searching your prepared history…":c!=null&&c.stage.includes("Reconciling")?"Checking later updates…":c!=null&&c.stage.includes("Thinking")?"Draken is thinking…":"Reading the snapshot context…",_=o.useRef(null),T=o.useRef(!0);o.useEffect(()=>{T.current&&_.current&&(_.current.scrollTop=_.current.scrollHeight)},[t.messages.length,v,b,x]);const p=[...t.items,...t.context],N=i||!j||!(s!=null&&s.ready);return e.jsxs("section",{className:"card text-chat","aria-label":"Chat with Draken",children:[e.jsxs("header",{className:"chat-heading",children:[e.jsx("img",{className:"chat-avatar",src:"/persona/chat-avatar.webp",alt:"Draken",width:"52",height:"52"}),e.jsxs("div",{children:[e.jsx("h2",{children:"Chat with Draken"}),e.jsx("p",{className:"small muted",children:"Same history. No microphone or audio."})]}),e.jsx("button",{type:"button",className:"btn btn-ghost",onClick:S,children:"Voice & call history"})]}),e.jsxs("div",{className:"chat-thread",ref:_,onScroll:()=>{const m=_.current;m&&(T.current=m.scrollHeight-m.scrollTop-m.clientHeight<80)},children:[!t.messages.length&&!v&&e.jsxs("div",{className:"chat-welcome",children:[e.jsx("h3",{children:"What would you like to pick up?"}),e.jsx("p",{children:"Ask about a project, a decision, or what still needs your attention. Draken will use the snapshot and prepared original history."})]}),t.messages.map(m=>e.jsxs("article",{className:`chat-message ${m.role}`,children:[m.role==="assistant"&&e.jsx("img",{className:"chat-avatar",src:"/persona/chat-avatar.webp",alt:"",width:"36",height:"36"}),e.jsxs("div",{className:"chat-bubble",children:[e.jsxs("div",{className:"chat-author",children:[e.jsx("strong",{children:m.role==="user"?"You":"Draken"}),e.jsx("time",{dateTime:m.created_at,children:new Date(m.created_at).toLocaleTimeString(void 0,{hour:"2-digit",minute:"2-digit"})})]}),e.jsx(Ee,{text:m.content,evidence:p})]})]},m.id)),v&&!(c!=null&&c.request_id&&(f||w&&!l))&&e.jsx("article",{className:"chat-message user",children:e.jsxs("div",{className:"chat-bubble",children:[e.jsx("strong",{children:"You"}),e.jsx("p",{className:"prose",children:v})]})}),b&&e.jsxs("div",{className:"chat-message assistant",children:[e.jsx("img",{className:"chat-avatar",src:"/persona/chat-avatar.webp",alt:"",width:"36",height:"36"}),e.jsxs("div",{className:"chat-bubble chat-thinking",role:"status","aria-label":"Chat status","aria-live":"polite",children:[e.jsx("span",{className:"spinner","aria-hidden":"true"}),x,e.jsx("span",{className:"small muted",children:"Your answer will appear here when it’s ready."})]})]}),w&&e.jsxs("div",{className:"alert warning",role:"alert",children:[e.jsx("strong",{children:(c==null?void 0:c.status)==="failed"?"Reply failed.":"Reply stopped."}),e.jsx("p",{children:(c==null?void 0:c.error)||"The question is retained. Nothing was marked reviewed."}),e.jsx("button",{className:"btn btn-secondary",disabled:N,onClick:()=>a((c==null?void 0:c.question)||""),children:"Retry chat reply"})]})]}),j&&e.jsxs(e.Fragment,{children:[!b&&e.jsx("p",{className:"small muted",role:"status",children:s!=null&&s.ready?`History cutoff: ${s.before?new Date(s.before).toLocaleString():"prepared snapshot"}. Refresh for later work.`:t.busy?"Preparing the briefing and history for chat…":s!=null&&s.briefingReady?"Prepare history before sending a message.":"Prepare the briefing and history first."}),(s==null?void 0:s.error)&&e.jsx("p",{role:"alert",className:"small",children:s.error}),e.jsxs("form",{className:"chat-compose",onSubmit:m=>{m.preventDefault(),!N&&n.trim()&&(T.current=!0,a())},children:[e.jsx("label",{htmlFor:"chat-question",className:"sr-only",children:"Message Draken"}),e.jsx("textarea",{id:"chat-question",rows:3,maxLength:4e3,value:n,disabled:N,onChange:m=>r(m.target.value),placeholder:"Ask Draken…",onKeyDown:m=>{var y;m.key==="Enter"&&!m.shiftKey&&!m.nativeEvent.isComposing&&(m.preventDefault(),n.trim()&&!N&&((y=m.currentTarget.form)==null||y.requestSubmit()))}}),e.jsxs("div",{className:"chat-compose-footer",children:[e.jsx("span",{className:"small muted",children:"Enter to send · Shift+Enter for a new line"}),f?e.jsxs("button",{type:"button",className:"btn btn-secondary",onClick:g,children:[e.jsx(hs,{size:14}),"Stop reply"]}):e.jsxs("button",{className:"btn btn-primary",disabled:N||!n.trim(),children:[e.jsx(ls,{size:16}),"Send message"]})]})]}),(s==null?void 0:s.briefingReady)&&!s.preparing&&!b&&e.jsx("button",{className:"btn btn-secondary chat-refresh",disabled:i,onClick:d,children:s.ready?"Refresh history":"Prepare history"})]}),!j&&e.jsx("p",{className:"small muted",children:"This sync is closed. Its chat is preserved; start a new sync to continue."}),e.jsx("p",{className:"small muted chat-boundary",children:"Messages stay with this sync. Calls remain in call history. Chatting never marks anything reviewed or saves decisions for you."})]})}function Ct({id:t,chat:s=!1,callIntent:n,consumeIntent:r,navigate:i,setGuard:l}){var ve,ke,Ne,le,se,fe,je;const[a,g]=o.useState(null),[d,S]=o.useState(null),[c,j]=o.useState(""),[f,w]=o.useState(""),[v,b]=o.useState(!1),[x,_]=o.useState(!1),[T,p]=o.useState(""),[N,m]=o.useState(""),[y,E]=o.useState(""),F=o.useRef(!0),X=o.useRef(null),I=k=>{F.current&&(g(k),p(k.decisions),m(k.carry_forward))},R=async(k,O)=>{j(k),w("");try{await O()}catch($){F.current&&w($ instanceof Error?$.message:"Something went wrong")}finally{F.current&&j("")}};o.useEffect(()=>(F.current=!0,Ue(t).then(I).catch(k=>{F.current&&w(k.message)}),()=>{F.current=!1}),[t]),o.useEffect(()=>{if(!(a!=null&&a.busy))return;let k=!1,O;const $=async()=>{try{const W=await et(t);if(k)return;if(W.busy)g(te=>te&&{...te,tree:W});else{const te=await Ue(t);k||I(te);return}}catch(W){k||w(W instanceof Error?W.message:"Could not refresh progress")}k||(O=setTimeout(()=>void $(),1e3))};return $(),()=>{k=!0,clearTimeout(O)}},[t,a==null?void 0:a.busy]),o.useEffect(()=>{S(null);const k=new AbortController;let O;const $=async()=>{try{const W=await(s?st:ns)(t,k.signal);k.signal.aborted||S(W)}catch{k.signal.aborted||S(null)}k.signal.aborted||(O=setTimeout(()=>void $(),a!=null&&a.busy?1e3:3e3))};return $(),()=>{k.abort(),clearTimeout(O)}},[t,a==null?void 0:a.busy,a==null?void 0:a.briefing,a==null?void 0:a.status,v,s]);const L=!!(a&&(T!==a.decisions||N!==a.carry_forward)),oe=!!y.trim();o.useEffect(()=>{l(()=>!(L||oe||v)||window.confirm(v?"Leave this page and end the call?":"Leave with unsaved notes or an unsent message?"));const O=$=>{(L||oe||v)&&($.preventDefault(),$.returnValue="")};return window.addEventListener("beforeunload",O),()=>{l(null),window.removeEventListener("beforeunload",O)}},[L,oe,v,l]);const ae=()=>{r(),_(!1)},B=!!(c||a!=null&&a.busy||v),ee=(a==null?void 0:a.status)==="open",pe=a?[...a.items,...a.context]:[],K=pe.some(k=>k.unavailable),me=()=>void R("Preparing your conversation…",async()=>{if(a){if(s&&L)throw new Error("Save or undo your note edits before preparing chat.");_(!s),L&&await Se(t,T,N),I(await it(t))}}),ge=()=>void R("Preparing history for your conversation…",async()=>{if(s&&L)throw new Error("Save or undo your note edits before refreshing history.");ae(),S(null),L&&await Se(t,T,N),I(await tt(t))}),De=(k=y)=>void R("Starting discussion…",async()=>{L&&await Se(t,T,N),I(await ot(t,k))}),H=(k=y)=>void R("Sending message…",async()=>{var W,te;if(ae(),L)throw new Error("Save your note edits, or undo them, before sending a message. Chat does not save decisions for you.");const O=((W=X.current)==null?void 0:W.text)===k?X.current:{text:k,id:ms()};X.current=O;let $;try{$=await Qs(t,k,O.id)}catch(Fe){const h=await Ue(t).catch(()=>null);if(((te=h==null?void 0:h.tree.run)==null?void 0:te.request_id)!==O.id)throw Fe;$=h}I($),E(""),X.current=null}),G=()=>{var k;return(k=a==null?void 0:a.tree.run)!=null&&k.question?s||a.tree.run.request_id?H(a.tree.run.question):De(a.tree.run.question):me()},ce=()=>{ae(),R("Stopping preparation…",async()=>{await rt(t)})},re=!(a!=null&&a.busy)&&(a==null?void 0:a.tree.run)&&["failed","cancelled","interrupted"].includes(a.tree.run.status);return o.useEffect(()=>{(re||d!=null&&d.error)&&ae()},[re,d==null?void 0:d.error]),e.jsxs("main",{className:"sync-detail",children:[e.jsxs("a",{className:"back-link",href:"/",onClick:k=>ue(k,i,"/"),children:[e.jsx(Es,{size:16}),"All syncs"]}),f&&e.jsx("div",{className:"alert error",role:"alert",children:f}),!a&&!f&&e.jsx("p",{role:"status",children:"Opening sync…"}),a&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"page-heading",children:[e.jsxs("div",{children:[e.jsx("span",{className:"eyebrow",children:"FROZEN CONVERSATION"}),e.jsxs("h1",{children:["Sync #",t]}),e.jsxs("p",{className:"muted",children:["Snapshot created ",new Date(a.snapshot_at).toLocaleString()," · ",a.item_count," entries · ",e.jsx("span",{className:`status ${a.status}`,children:a.status==="completed"?"reviewed":a.status})]}),e.jsx(fs,{cost:a.aggregation_cost})]}),ee&&e.jsxs("button",{className:"btn btn-secondary",disabled:B||K||!!(a.tree.run&&!a.tree.complete),onClick:()=>{window.confirm(`Mark these ${a.item_count} snapshot entries reviewed? Later activity is not affected. This does not mean every spoken suggestion was agreed.`)&&R("Marking snapshot reviewed…",async()=>{I(await ht(t,T,N))})},children:[e.jsx(As,{size:16}),"Mark reviewed"]})]}),K&&e.jsxs("div",{className:"alert warning",role:"alert",children:[e.jsx("strong",{children:"Original session evidence unavailable."}),e.jsx("p",{children:"Restore the original session files to inspect the missing excerpts, prepare replies, call or mark this snapshot reviewed. Your conversation and saved notes are still available; Draken keeps pointers, not copies of original session text."})]}),(c||a.busy)&&!(s&&(c==="Sending message…"||(ve=a.tree.run)!=null&&ve.question&&a.tree.run.status==="running"))&&e.jsxs("div",{className:"working",role:"status",children:[e.jsx("span",{className:"spinner"}),c||(a.recap_state==="running"?"Making a short conversation recap…":d!=null&&d.preparing?"Preparing searchable history…":((ke=a.tree.run)==null?void 0:ke.stage)||"Preparing your conversation…"),a.busy&&e.jsx("button",{className:"btn btn-secondary",onClick:ce,children:"Cancel preparation"})]}),e.jsx(ze,{enabled:a.busy}),a.busy&&!((Ne=a.tree.run)!=null&&Ne.question)&&a.recap_state!=="running"&&e.jsx("p",{className:"small muted",children:"The complete new snapshot is being reconciled. Large histories can take a while. Leaving or reloading will not start your microphone."}),re&&!(s&&((le=a.tree.run)!=null&&le.question))&&e.jsxs("div",{className:"alert warning",role:"alert",children:[e.jsx("strong",{children:(se=a.tree.run)!=null&&se.question?"Reply stopped.":"Preparation stopped."}),e.jsx("p",{children:((fe=a.tree.run)==null?void 0:fe.error)||"Your snapshot is retained. Nothing was marked reviewed."}),e.jsx("button",{className:"btn btn-primary",disabled:B||K,onClick:G,children:(je=a.tree.run)!=null&&je.question?"Retry reply":s?"Retry preparation":"Retry preparation & call"})]}),ee&&!a.briefing&&!a.busy&&!re&&a.snapshot_version===2&&e.jsx("button",{className:"btn btn-primary",disabled:B||K,onClick:me,children:s?"Prepare for chat":"Prepare & call"}),s?e.jsx(St,{sync:a,readiness:d,draft:y,setDraft:E,disabled:B||K,sending:c==="Sending message…",onSend:H,onCancel:ce,onPrepareHistory:ge,onVoice:()=>i(`/syncs/${t}`)}):e.jsx(Nt,{sync:a,readiness:d,onPrepareHistory:ge,disabled:B||K,onActiveChange:b,onChat:()=>{ae(),i(`/syncs/${t}/chat`)},autoStart:(n||x)&&!re&&!K,onAutoStartHandled:ae,beforeStart:async()=>{L&&I(await Se(t,T,N));const k=await ns(t);if(S(k),!k.ready)throw new Error("History needs preparation before calling. Use Prepare history first.")},onClosed:async()=>{await R("Saving a short recap…",async()=>{I(await ss(t))})}},t),e.jsxs("section",{className:"card recap-card",children:[e.jsxs("div",{className:"section-heading",children:[e.jsx("h2",{children:"At a glance"}),e.jsx("button",{className:"btn btn-secondary",disabled:B,onClick:()=>void R("Summarizing the conversation…",async()=>I(await ss(t))),children:a.recap?"Refresh recap":"Make recap"})]}),e.jsx("p",{className:"prose",children:a.recap||"Use Make recap to condense this conversation. Ending a call also requests a recap. The full briefing and original history remain below."}),e.jsx("p",{className:"small muted",children:"Automatic summary, not saved decisions or proof of agreement."}),a.recap_error&&e.jsx("p",{role:"alert",className:"small",children:a.recap_error})]}),a.memory.length>0&&e.jsxs("details",{className:"detail-section",children:[e.jsx("summary",{children:"Previous sync recaps"}),a.memory.map(k=>e.jsxs("article",{className:"memory-recap",children:[e.jsxs("a",{href:`/syncs/${k.sync_id}`,onClick:O=>ue(O,i,`/syncs/${k.sync_id}`),children:["Sync #",k.sync_id]})," ",e.jsx("span",{className:"small muted",children:k.status==="open"?"not marked reviewed":k.status||"historical"}),e.jsx("p",{className:"prose",children:k.recap||"No automatic recap in this older snapshot."}),k.decisions&&e.jsxs("p",{className:"small prose",children:["Saved decisions: ",k.decisions]}),k.carry_forward&&e.jsxs("p",{className:"small prose",children:["Carried forward: ",k.carry_forward]})]},k.sync_id))]}),e.jsxs("details",{className:"detail-section",open:!a.messages.length&&!!a.briefing,children:[e.jsx("summary",{children:"Full briefing"}),e.jsxs("section",{className:"briefing-card",children:[e.jsx("p",{className:"small muted",children:"This snapshot contains the entries captured during preparation, not a live view. Check the original source dates in the evidence."}),(d==null?void 0:d.before)&&e.jsxs("p",{className:"small muted",children:["Conversation history cutoff: ",new Date(d.before).toLocaleString(),". Later activity waits for another preparation."]}),a.briefing?e.jsx(Ee,{text:a.briefing,evidence:pe}):e.jsx("p",{children:"No briefing yet."}),a.snapshot_version<2&&e.jsxs("div",{className:"alert warning",children:["This is a historical capped snapshot. Notes and discussion are preserved.",ee&&e.jsx("button",{className:"btn btn-secondary",disabled:B,onClick:()=>{window.confirm("Expand this legacy snapshot to currently eligible history? Existing notes and citations are retained.")&&R("Expanding snapshot…",async()=>I((await at(t)).sync))},children:"Expand to full history"})]})]})]}),!s&&e.jsxs("details",{className:"detail-section",children:[e.jsxs("summary",{children:["Saved text conversation (",a.messages.length,")"]}),e.jsxs("section",{className:"discussion",children:[a.messages.map(k=>e.jsxs("div",{className:`message ${k.role}`,children:[e.jsx("span",{className:"message-author",children:k.role==="user"?"You":"Draken"}),e.jsx(Ee,{text:k.content,evidence:pe})]},k.id)),e.jsx("button",{className:"btn btn-secondary",disabled:v,onClick:()=>{ae(),i(`/syncs/${t}/chat`)},children:"Open chat"})]})]}),e.jsxs("details",{className:"detail-section",children:[e.jsxs("summary",{children:["Decisions & carry-forward",L?" · unsaved":""]}),e.jsxs("section",{className:"notes-card",children:[e.jsxs("div",{className:"notes-grid",children:[e.jsxs("div",{children:[e.jsx("label",{htmlFor:"decisions",children:"Decisions"}),e.jsx("textarea",{id:"decisions",rows:4,maxLength:4e3,disabled:!ee||B,value:T,onChange:k=>p(k.target.value)})]}),e.jsxs("div",{children:[e.jsx("label",{htmlFor:"carry-forward",children:"Carry into the next sync"}),e.jsx("textarea",{id:"carry-forward",rows:4,maxLength:4e3,disabled:!ee||B,value:N,onChange:k=>m(k.target.value)})]})]}),e.jsx("p",{className:"small muted",children:"Only these explicitly saved notes are decisions. A call or its automatic recap does not mark anything agreed or reviewed."}),ee&&e.jsx("button",{className:"btn btn-secondary",disabled:B||!L,onClick:()=>void R("Saving notes…",async()=>I(await Se(t,T,N))),children:"Save notes"})]})]}),e.jsxs("details",{className:"detail-section",children:[e.jsx("summary",{children:"Evidence & preparation details"}),e.jsx(pt,{syncId:t,progress:a.tree,evidence:pe,onResume:ee?G:void 0,resumeEnabled:!B&&!K,onCancel:ce}),e.jsx(as,{items:a.items,title:"New evidence in this snapshot"}),e.jsx(as,{items:a.context,title:"Earlier context — not new progress"})]}),ee&&e.jsxs("div",{className:"detail-footer",children:[e.jsx("p",{className:"small muted",children:"Included does not mean reviewed. You can return to this sync at this URL, or start a separate one for new activity."}),e.jsx("button",{className:"btn btn-ghost",disabled:B,onClick:()=>{window.confirm("Discard this sync and release its unreviewed entries? Its history is retained.")&&R("Discarding sync…",async()=>I(await ut(t)))},children:"Discard sync"})]})]})]})}const os=t=>new Date(t).toLocaleString(),Et={pi:"pi v3 JSONL",codex:"Rollout JSONL",claude:"Transcript JSONL"};function Tt({open:t}){const[s,n]=o.useState(!1),[r,i]=o.useState(null),[l,a]=o.useState(!0),[g,d]=o.useState(!1),[S,c]=o.useState(""),[j,f]=o.useState(""),[w,v]=o.useState(null),b=o.useRef(!0),x=o.useRef(!1);o.useEffect(()=>(b.current=!0,()=>{b.current=!1}),[]),o.useEffect(()=>{if(!t||!s||g)return;let p=!0;const N=async()=>{try{const[y,E]=await Promise.all([ts(),Ge()]);p&&!x.current&&(i(y),a(E.busy||E.active_call),f(""))}catch(y){p&&!x.current&&f(y instanceof Error?y.message:"Could not read session sources")}};N();const m=setInterval(()=>void N(),4e3);return()=>{p=!1,clearInterval(m)}},[t,s,g]);const _=async(p,N)=>{if(!r||l||j||x.current)return;const m=r;x.current=!0,d(!0),c(""),N&&i(N);try{const y=await p();b.current&&i(y)}catch(y){b.current&&(N&&i(m),c(y instanceof Error?y.message:"Could not update session sources"))}finally{x.current=!1,b.current&&d(!1)}},T=!r||l||g||!!j;return e.jsxs("details",{className:"source-settings",onToggle:p=>n(p.currentTarget.open),children:[e.jsx("summary",{children:"Agents & sessions"}),e.jsx("p",{className:"small muted",children:"Directory presence is not an installation check. Opening this panel reads recorded metadata; it does not scan transcripts, index embeddings or call a model."}),e.jsx("p",{className:"small muted",children:"Enable each history source before importing it. Codex and Claude history start off; existing pi choices are preserved. Enabling a source allows its logs into the next scan, sync or opted-in background batch. New sessions from enabled agents are selected by default. Summarization still runs through pi, regardless of which agent produced the history."}),!r&&e.jsx("p",{className:"small muted",role:"status",children:"Loading session inventory…"}),e.jsxs("button",{type:"button",className:"btn btn-secondary",disabled:T||!(r!=null&&r.agents.some(p=>p.enabled)),onClick:()=>void _(async()=>{const p=await Js();return b.current&&v(p),ts()}),children:[e.jsx(zs,{size:15,"aria-hidden":"true"}),"Scan enabled agents"]}),l&&r&&e.jsx("p",{className:"small muted",children:"Source changes are paused while a call or sync preparation is active."}),g&&e.jsx("p",{className:"small muted",role:"status",children:"Updating session sources…"}),r==null?void 0:r.agents.map(p=>{const N=r.sessions.filter(m=>m.agent===p.id);return e.jsxs("section",{className:"agent-source","aria-labelledby":`${p.id}-source-title`,children:[e.jsxs("div",{className:"section-heading",children:[e.jsx("h3",{id:`${p.id}-source-title`,children:p.name}),e.jsx("span",{className:"status",children:Et[p.id]})]}),e.jsxs("label",{className:"index-toggle",children:[e.jsx("input",{type:"checkbox",role:"switch","aria-label":`Enable ${p.name} history`,checked:p.enabled,disabled:T,onChange:m=>{const y=m.target.checked;_(()=>Zs(p.id,y),{...r,agents:r.agents.map(E=>E.id===p.id?{...E,enabled:y}:E)})}}),e.jsxs("span",{children:[e.jsxs("strong",{children:["Include ",p.name," history"]}),e.jsx("span",{className:"small muted",children:p.enabled?"Enabled for scanning and future syncs":"Off — transcripts are not scanned or indexed"})]})]}),p.roots.map(m=>e.jsxs("div",{children:[e.jsx("p",{className:"small muted",children:m.status==="present"?"Directory found":m.status==="missing"?"Directory not found":"Directory unavailable"}),e.jsx("code",{className:"source-path",children:m.path})]},m.path)),e.jsxs("p",{className:"small muted",children:[N.length," recorded sessions · ",N.filter(m=>m.included).length," selected · ",N.filter(m=>m.missing).length," unavailable at last scan"]}),!N.length&&e.jsxs("p",{className:"small muted",children:["No ",p.name," sessions recorded yet.",p.enabled?" Scan enabled agents to discover them.":" Enable this source before scanning."]}),e.jsx("div",{className:"session-list","aria-label":`Discovered ${p.name} sessions`,children:N.map(m=>e.jsxs("label",{className:"session-source",children:[e.jsx("input",{type:"checkbox",checked:!!m.included,disabled:T||!p.enabled||!!m.missing,"aria-label":`Include ${m.name||"session"} (${m.id})`,onChange:y=>{const E=y.target.checked;_(()=>Xs(m.id,E),{...r,sessions:r.sessions.map(F=>F.id===m.id?{...F,included:Number(E)}:F)})}}),e.jsxs("span",{children:[e.jsx("strong",{children:m.name||m.cwd.split(/[\\/]/).filter(Boolean).pop()||m.id}),e.jsx("span",{className:"source-cwd",title:m.cwd,children:m.cwd||"Workspace unavailable"}),e.jsxs("span",{className:"small",children:[m.included?"Selected":"Excluded"," · ",m.pending," unreviewed ",m.pending===1?"entry":"entries",m.missing?" · unavailable at last scan":""]}),e.jsxs("span",{className:"source-session-meta small muted",children:["Session ",m.external_id||m.id," · Last recorded change: ",os(m.modified_at)]}),e.jsx("code",{className:"source-path",children:m.path})]})]},m.id))})]},p.id)}),r&&e.jsxs("p",{className:"small muted",children:[r.history_initialized&&r.history_since?`Existing history baseline: ${os(r.history_since)}. It is preserved.`:"All indexed history is eligible; there is no rolling time window."," Source choices do not edit existing frozen syncs or mark evidence reviewed. Scanning does not generate summaries or start a call. Keep the original logs: evidence is verified from them, not copied into Draken."]}),w&&e.jsxs("p",{className:"small muted",role:"status",children:["Last requested scan: ",w.files," candidate log files checked · ",w.added," new records recorded."]}),w&&w.warnings.length>0&&e.jsx("ul",{className:"source-warnings small","aria-label":"Scan warnings",children:w.warnings.map((p,N)=>e.jsx("li",{children:p},N))}),(S||j)&&e.jsx("p",{className:"small",role:"alert",children:S||j})]})}function At(){const[t,s]=o.useState(!1),[n,r]=o.useState(null),[i,l]=o.useState(!1),[a,g]=o.useState(""),d=o.useRef(null);o.useEffect(()=>{var c,j,f;t&&!((c=d.current)!=null&&c.open)?(j=d.current)==null||j.showModal():t||(f=d.current)==null||f.close()},[t]),o.useEffect(()=>{if(!t||i)return;let c=!0;const j=async()=>{try{const w=await Ys();c&&(r(w),g(""))}catch(w){c&&g(w instanceof Error?w.message:"Could not read settings")}};j();const f=setInterval(()=>void j(),4e3);return()=>{c=!1,clearInterval(f)}},[t,i]);const S=n&&{off:"Off",waiting:n.pending_records?`${n.pending_records} source changes waiting for a batch`:"Waiting for the next background check",scanning:"Checking session sources",indexing:"Indexing in the background",paused:"Paused for foreground work",stopping:"Stopping background work",error:"Background indexing needs attention"}[n.phase];return e.jsxs(e.Fragment,{children:[e.jsxs("button",{type:"button",className:"btn btn-secondary header-settings","aria-haspopup":"dialog",onClick:()=>s(!0),children:[e.jsx(Fs,{size:16,"aria-hidden":"true"}),"Settings"]}),e.jsxs("dialog",{ref:d,className:"settings-dialog","aria-labelledby":"settings-title",onCancel:c=>{c.preventDefault(),s(!1)},onClose:c=>{c.currentTarget.open||s(!1)},children:[e.jsxs("div",{className:"section-heading",children:[e.jsx("h2",{id:"settings-title",children:"Settings"}),e.jsx("button",{type:"button",className:"icon-button","aria-label":"Close settings",autoFocus:!0,onClick:()=>s(!1),children:e.jsx(Ke,{size:18,"aria-hidden":"true"})})]}),e.jsxs("label",{className:"index-toggle",children:[e.jsx("input",{type:"checkbox",role:"switch",checked:(n==null?void 0:n.enabled)||!1,disabled:!n||i,onChange:async c=>{const j=c.target.checked,f=n;l(!0),g(""),r(w=>w&&{...w,enabled:j});try{r(await Ks(j))}catch(w){r(f),g(w instanceof Error?w.message:"Could not save settings")}finally{l(!1)}}}),e.jsxs("span",{children:[e.jsx("strong",{children:"Automatically index history"}),e.jsx("span",{className:"small muted",children:"Prepare search and call history in the background, off by default."})]})]}),e.jsx("p",{className:"small muted",children:"While the server is running, check once a minute and index only when at least 64 changed source records have accumulated. Smaller batches wait until you prepare a sync, use Prepare history or search; there is no timed flush. Call Draken stays disabled until its history is ready. Calls, sync preparation and searches take priority. Newly discovered sessions from enabled agents are selected by default; agent and session exclusions remain respected."}),e.jsx("p",{className:"small muted",children:"This scans text logs and prepares local search embeddings; first use may download the pinned search model. It does not create or change frozen syncs, mark anything reviewed, use your microphone, or run summary models. The final aggregation still runs when you click Sync with Draken."}),n&&e.jsxs("p",{className:"small muted",role:"status",children:[i?"Saving…":S,n.last_completed_at&&` · Last completed batch: ${new Date(n.last_completed_at).toLocaleString()}`]}),(a||(n==null?void 0:n.error))&&e.jsx("p",{className:"small",role:"alert",children:a||(n==null?void 0:n.error)}),e.jsx(ze,{enabled:t&&(n==null?void 0:n.phase)==="indexing",backgroundOnly:!0}),e.jsx(Tt,{open:t}),e.jsx(xs,{active:t,always:!0})]})]})}function Pt(){const{isAuthenticated:t,isLoading:s,authEnabled:n,username:r,logout:i}=ps(),[l,a]=o.useState(window.location.pathname),[g,d]=o.useState(null),S=o.useRef(null),c=o.useRef(l),j=o.useCallback(b=>{S.current=b},[]),f=o.useCallback((b,x=!1)=>{S.current&&!S.current()||(window.history.pushState(null,"",b),c.current=b,a(b),d(x?Number(b.split("/").pop()):null),window.scrollTo(0,0))},[]);if(o.useEffect(()=>{const b=()=>{if(S.current&&!S.current()){window.history.pushState(null,"",c.current);return}c.current=window.location.pathname,a(c.current),d(null)};return window.addEventListener("popstate",b),()=>window.removeEventListener("popstate",b)},[]),s)return e.jsxs("div",{className:"app-loading",children:[e.jsx("span",{className:"spinner"}),"Opening Draken…"]});if(!t)return e.jsx(Vs,{});const w=/^\/syncs\/([1-9]\d*)(\/chat)?\/?$/.exec(l),v=w?Number(w[1]):null;return e.jsxs("div",{className:"app-container",children:[e.jsxs("header",{className:"header",children:[e.jsxs("a",{className:"brand",href:"/",onClick:b=>ue(b,f,"/"),"aria-label":"Draken sync history",children:[e.jsx("img",{src:"/favicon.png",alt:""}),e.jsxs("div",{children:[e.jsx("strong",{children:"Draken"}),e.jsx("span",{children:"Session sync"})]})]}),e.jsxs("div",{className:"header-right",children:[e.jsx("a",{href:"/history",onClick:b=>ue(b,f,"/history"),children:"Search history"}),e.jsx(At,{}),n&&e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"muted small",children:r}),e.jsx("button",{className:"icon-button",onClick:()=>{(!S.current||S.current())&&i()},"aria-label":"Sign out",children:e.jsx(Rs,{size:18})})]})]})]}),v&&Number.isSafeInteger(v)?e.jsx(Ct,{id:v,chat:!!(w!=null&&w[2]),callIntent:g===v,consumeIntent:()=>d(null),navigate:f,setGuard:j},v):/^\/history(?:\/H[a-f0-9]{24})?\/?$/.test(l)?e.jsx(yt,{navigate:f,reference:l.split("/")[2]},l):l==="/"?e.jsx(gt,{navigate:f}):e.jsxs("main",{className:"sync-home",children:[e.jsx("h1",{children:"Page not found"}),e.jsx("a",{href:"/",onClick:b=>ue(b,f,"/"),children:"All syncs"})]})]})}function _t(){return e.jsx(Us,{children:e.jsx(Pt,{})})}bs.createRoot(document.getElementById("root")).render(e.jsx(ks.StrictMode,{children:e.jsx(_t,{})}));
@@ -1 +0,0 @@
1
- .dp-stage{position:relative;isolation:isolate;margin:0;width:100%;height:100%;min-height:280px;overflow:hidden;border:2px solid var(--ink, #111);background:#707c72}.dp-poster,.dp-canvas{display:block;position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;object-fit:cover}.dp-canvas{opacity:0}.dp-canvas.is-ready{opacity:1}.dp-caption{position:absolute;bottom:15px;left:15px;padding:9px 11px;background:#172923ed;color:#fff5dc;font:800 10px/1.4 Avenir Next,Arial,sans-serif;letter-spacing:.12em;pointer-events:none}.dp-caption-sub{display:block;margin-top:3px;color:#d2d9cc;font-size:8px;letter-spacing:.08em}.dp-dot{display:inline-block;width:6px;height:6px;margin-right:7px;background:#e5bc63;border-radius:50%;vertical-align:middle}.dp-tools{position:absolute;right:15px;top:15px}.dp-tools button{padding:8px 10px;border:1px solid #c5b995;color:#fff5dc;background:#172923ed;font:700 10px/1.3 Avenir Next,Arial,sans-serif;cursor:pointer}.dp-tools button:hover:not(:disabled){background:#30483b}.dp-tools button:focus-visible{outline:3px solid #f2c230;outline-offset:3px}.dp-tools button:disabled{cursor:default}.dp-fallback{position:absolute;left:12px;right:12px;top:60px;color:#fff5dc;background:#172923ed;padding:8px 12px;font-size:12px;line-height:1.5}@media(max-width:760px){.dp-stage{min-height:190px}.dp-caption{left:10px;bottom:10px;padding:7px 9px;font-size:9px}.dp-tools{right:10px;top:10px}}@media(forced-colors:active){.dp-caption,.dp-tools button,.dp-fallback{color:CanvasText;background:Canvas;border:1px solid CanvasText}.dp-caption-sub{color:CanvasText}}:root{font-family:Avenir Next,Futura,Century Gothic,Arial Narrow,Arial,sans-serif;font-synthesis:none;color-scheme:light;color:var(--ink);background:var(--paper);--paper: #c7c6c0;--panel: #deddd7;--ink: #111111;--line: var(--ink);--rule: #a9a79f;--surface-muted: #bbb9b1;--muted: #4f4d47;--accent: #9136d8;--red: #e33b2e;--blue: #1746a2;--yellow: #f2c230;--green: #0b7a53;--success-surface: #dfeee4;--warning-surface: #fff0b8;--danger-surface: #fbe0dc;--concrete-noise: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.72' numOctaves='4' seed='8' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3CfeComponentTransfer%3E%3CfeFuncA type='table' tableValues='0 .32'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E")}*{box-sizing:border-box}body{margin:0;background-color:var(--paper);background-image:var(--concrete-noise),radial-gradient(circle at 2rem 2rem,rgb(39 39 37 / 34%) 0 2px,rgb(255 255 255 / 24%) 2.5px 3.5px,transparent 4px),linear-gradient(to bottom,rgb(17 17 17 / 14%) 1px,transparent 1px),linear-gradient(to right,rgb(17 17 17 / 12%) 1px,transparent 1px);background-position:0 0,0 0,-1px -1px,-1px -1px;background-size:180px 180px,14rem 14rem,28rem 14rem,28rem 14rem;background-blend-mode:soft-light,multiply,multiply,multiply}button,input,textarea,select{font:inherit;border-radius:0}button{cursor:pointer}button,input,textarea,select{transition:background-color .12s,transform .12s,box-shadow .12s}button:disabled,input:disabled,textarea:disabled,select:disabled{cursor:not-allowed;opacity:.55;box-shadow:none;transform:none}:where(button,a,input,textarea,select,summary):focus-visible{outline:3px solid var(--accent);outline-offset:3px}::selection{background:#f4a097;color:var(--ink)}input[type=checkbox]{accent-color:var(--accent);width:18px;height:18px;flex:0 0 18px;margin:2px 0 0}textarea,.input{width:100%;min-width:0;border:2px solid var(--line);padding:12px 14px;background:var(--panel);color:var(--ink);resize:vertical;line-height:1.65}textarea::placeholder,.input::placeholder{color:var(--muted);opacity:1}h1,h2,h3{letter-spacing:-.04em;font-weight:900;text-transform:uppercase;overflow-wrap:anywhere}h1{font-size:clamp(32px,3.4vw,48px);line-height:1.04;margin:16px 0;letter-spacing:-.055em}h2{font-size:20px;margin:0 0 16px}h3{font-size:16px}p{line-height:1.7}.muted{color:var(--muted)}.small{font-size:12px}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.header{min-height:84px;display:flex;align-items:center;justify-content:space-between;gap:16px;padding:14px max(24px,calc((100vw - 1550px)/2 + 24px));border-bottom:2px solid var(--line);background:var(--panel)}.brand{display:flex;align-items:center;gap:14px}.brand img{width:44px;height:44px;object-fit:contain}.brand strong{display:block;font-size:28px;font-weight:900;letter-spacing:-.06em;text-transform:uppercase;line-height:1}.brand span{display:block;font-size:10px;font-weight:800;color:var(--muted);letter-spacing:.12em;text-transform:uppercase;margin-top:6px}.header-right{display:flex;align-items:center;flex-wrap:wrap;gap:16px;min-width:0}.header-right .header-settings{min-height:36px;padding:7px 10px;font-size:10px}.settings-dialog{--settings-padding: 24px;width:min(620px,calc(100% - 32px));max-height:calc(100dvh - 32px);margin:auto;padding:var(--settings-padding);border:2px solid var(--line);background:var(--panel);color:var(--ink);box-shadow:8px 8px 0 var(--ink);overflow:auto;overscroll-behavior:contain}.settings-dialog::backdrop{background:#1119}.settings-dialog>.section-heading{position:sticky;top:calc(-1 * var(--settings-padding));z-index:1;margin-top:calc(-1 * var(--settings-padding));padding-block:var(--settings-padding) 12px;background:var(--panel)}.section-heading{display:flex;align-items:center;justify-content:space-between;gap:12px}.section-heading>*{min-width:0}.section-heading h2{margin-bottom:0}.source-path{display:block;overflow-wrap:anywhere;font-size:11px;color:var(--muted);line-height:1.65;background:var(--paper);border:1px solid var(--rule);padding:10px}.session-list{margin-top:20px;max-height:440px;overflow-y:auto;padding:3px}.session-source{display:flex;align-items:flex-start;gap:10px;padding:12px;margin-bottom:10px;border:2px solid var(--line);cursor:pointer;background:var(--paper)}.session-source:has(input:checked){background:var(--panel);box-shadow:inset 4px 0 0 var(--accent)}.session-source>span{min-width:0}.session-source strong{display:block;font-size:13px;overflow-wrap:anywhere;font-weight:800}.source-cwd{display:block;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;color:var(--muted);font-size:11px;margin:5px 0}.session-source .small{font-size:10px}.page-heading{display:flex;justify-content:space-between;align-items:center;gap:24px}.page-heading>div{min-width:0}.page-heading>.btn{flex-shrink:0}.page-heading h1{max-width:22ch;text-wrap:balance}.page-heading p{font-size:13px;margin-bottom:0}.eyebrow{display:inline-block;padding:6px 8px;border:1px solid var(--line);background:var(--yellow);font-size:10px;font-weight:900;letter-spacing:.1em}.btn{display:inline-flex;justify-content:center;align-items:center;gap:9px;min-height:42px;padding:11px 16px;border:2px solid var(--line);font-size:11px;font-weight:900;letter-spacing:.07em;text-transform:uppercase;line-height:1.4}.btn svg,.icon-button svg{flex-shrink:0}.btn-primary{color:#fff;background:var(--accent);box-shadow:4px 4px 0 var(--ink)}.btn-secondary{color:var(--ink);background:var(--panel)}.btn-ghost{color:var(--muted);background:transparent;border-color:transparent}.btn-primary:hover:not(:disabled),.btn-secondary:hover:not(:disabled){transform:translate(-2px,-2px);box-shadow:4px 4px 0 var(--ink)}.btn-secondary:hover:not(:disabled),.icon-button:hover:not(:disabled){background:var(--yellow)}.btn-ghost:hover:not(:disabled){color:var(--ink);border-color:var(--line);background:var(--danger-surface)}.icon-button{display:inline-flex;align-items:center;justify-content:center;min-width:36px;min-height:36px;border:2px solid var(--line);padding:7px;background:var(--panel);color:var(--ink)}.btn:active:not(:disabled),.icon-button:active:not(:disabled){transform:translate(1px,1px);box-shadow:none}.card{background:var(--panel);border:2px solid var(--line);padding:26px;margin-bottom:28px;box-shadow:6px 6px 0 var(--surface-muted)}.briefing-card,.welcome{box-shadow:8px 8px 0 var(--accent)}.welcome{text-align:center;padding:40px 30px}.welcome h2{font-size:clamp(22px,2.2vw,30px);margin-top:24px}.welcome>p{color:var(--muted);max-width:540px;margin:18px auto;font-size:14px}.status{display:inline-block;font-size:10px;line-height:1.3;letter-spacing:.03em;border:1px solid var(--line);padding:4px 7px;background:var(--surface-muted);color:var(--ink);vertical-align:middle;font-weight:800;text-transform:uppercase;white-space:nowrap}.status.open,.status.running{background:var(--yellow)}.status.completed,.status.done,.status.cached{background:var(--success-surface);border-color:var(--green)}.status.failed,.status.cancelled,.status.interrupted{background:var(--danger-surface);border-color:var(--red)}.prose{white-space:pre-wrap;overflow-wrap:anywhere;line-height:1.85;font-size:14px}.briefing-card>.prose{padding:18px 0 8px}.citation{display:inline;background:var(--panel);border:1px solid var(--blue);color:var(--blue);font-size:12px;font-weight:800;padding:2px 5px;vertical-align:baseline;margin:0 2px}.citation:hover{background:var(--yellow)}.discussion{box-shadow:6px 6px 0 var(--ink)}.message{padding:16px 18px;margin:16px 0;border:1px solid var(--rule);border-left:4px solid var(--accent);background:var(--panel)}.message.user{background:var(--paper);border-left-color:var(--blue)}.message-author{font-size:10px;color:var(--ink);font-weight:900;text-transform:uppercase;letter-spacing:.1em;display:block;margin-bottom:10px}.discussion form{margin-top:20px}.form-footer{display:flex;justify-content:space-between;align-items:center;gap:12px;margin-top:14px}.notes-card{box-shadow:6px 6px 0 var(--yellow)}.notes-grid{display:grid;grid-template-columns:1fr 1fr;gap:18px;margin:22px 0 10px}.notes-grid>div{min-width:0}.notes-grid label{font-size:12px;font-weight:800}.notes-grid textarea{margin-top:9px;font-size:13px;min-height:165px}.alert{padding:14px 16px;border:2px solid var(--line);border-left-width:6px;font-size:12px;line-height:1.7;margin-bottom:20px;overflow-wrap:anywhere;color:var(--ink)}.alert.error{background:var(--danger-surface);border-left-color:var(--red)}.alert.warning{background:var(--warning-surface);border-left-color:var(--yellow)}summary{cursor:pointer}.working{display:flex;align-items:center;gap:10px;font-size:12px;font-weight:700;color:var(--ink);margin:18px 0;padding:12px;background:var(--warning-surface);border:2px solid var(--line)}.spinner{width:18px;height:18px;flex-shrink:0;display:inline-block;border:2px solid currentColor;border-top-color:transparent;border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.tree-card progress,.history-progress progress{-webkit-appearance:none;-moz-appearance:none;appearance:none;display:block;width:100%;height:14px;border:2px solid var(--line);border-radius:0;background:var(--paper);accent-color:var(--accent)}.tree-card progress::-webkit-progress-bar,.history-progress progress::-webkit-progress-bar{background:var(--paper)}.tree-card progress::-webkit-progress-value,.history-progress progress::-webkit-progress-value{background:var(--accent)}.tree-card progress::-moz-progress-bar,.history-progress progress::-moz-progress-bar{background:var(--accent)}.tree-stats{display:flex;flex-wrap:wrap;gap:10px 18px;margin:12px 0;color:var(--muted);font-size:11px}.tree-browser{margin-top:20px;font-size:12px}.tree-browser>summary{font-weight:800;padding:6px 0}.tree-browser ul{list-style:none;padding-left:16px;margin:8px 0}.tree-browser>ul{padding-left:0}.tree-node{display:flex;align-items:center;min-width:0;gap:6px;padding:8px 0;border-bottom:1px solid var(--rule)}.tree-toggle{flex:0 0 28px;min-height:28px;border:1px solid transparent;background:transparent;color:var(--ink);padding:3px}.tree-toggle:hover:not(:disabled){border-color:var(--line);background:var(--yellow)}.tree-label{flex:1;min-width:0;min-height:28px;border:0;background:transparent;color:var(--ink);text-align:left;font-size:12px;overflow-wrap:anywhere}.tree-label:hover:not(:disabled){color:var(--blue);text-decoration:underline}.node-inspector{margin-top:22px;border:2px solid var(--line);border-top:5px solid var(--accent);padding:18px}.node-observation{margin:18px 0}.node-observation>strong{font-size:13px}.node-observation .prose{font-size:13px;margin-top:10px}.evidence-section{margin-top:34px}.evidence-section h3{line-height:1.6}.count{display:inline-block;background:var(--yellow);color:var(--ink);border:1px solid var(--line);padding:2px 7px;font-size:11px;margin-left:7px;vertical-align:middle}.evidence{background:var(--panel);border:2px solid var(--line);margin:10px 0;scroll-margin-top:24px}.evidence[open]{box-shadow:4px 4px 0 var(--blue)}.evidence summary{display:flex;align-items:center;gap:12px;padding:14px;list-style:none}.evidence summary::-webkit-details-marker{display:none}.evidence summary:hover{background:var(--paper)}.reference{border:1px solid var(--line);background:var(--yellow);font:11px ui-monospace,monospace;padding:6px;color:var(--ink);flex-shrink:0}.evidence-title{min-width:0;flex:1}.evidence-title strong{display:block;color:var(--ink);font-size:12px;font-weight:800;overflow-wrap:anywhere}.evidence-title>span{display:block;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;font-size:12px;color:var(--muted);margin-top:5px}.role-label{font-size:10px;color:var(--muted)}.evidence-body{border-top:1px solid var(--rule);padding:16px}dl{display:grid;grid-template-columns:75px minmax(0,1fr);font:11px ui-monospace,monospace;gap:8px;line-height:1.8}dt{color:var(--muted)}dd{margin:0;overflow-wrap:anywhere;color:var(--ink)}pre{white-space:pre-wrap;overflow-wrap:anywhere;font:12px/1.8 ui-monospace,monospace;color:var(--ink);max-height:550px;overflow-y:auto}.evidence-controls{margin:16px 0}.evidence-controls .input{font-size:12px}.pagination{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-top:12px;font-size:11px;color:var(--muted)}.app-loading{min-height:100vh;display:flex;align-items:center;justify-content:center;gap:15px;color:var(--ink);font-weight:800}.login-page{min-height:100vh;display:grid;place-items:center;padding:28px}.login-card{background:var(--panel);border:2px solid var(--line);box-shadow:10px 10px 0 var(--accent);padding:36px;width:min(100%,420px)}.login-header{text-align:center;margin-bottom:28px}.login-logo{width:64px;height:64px;object-fit:contain}.login-header h1{font-size:40px}.login-subtitle{color:var(--muted);font-size:13px}.form-group{margin-bottom:20px}.form-group label{display:block;font-size:11px;font-weight:900;text-transform:uppercase;letter-spacing:.06em;margin-bottom:9px}.input-with-icon{position:relative}.input-icon{position:absolute;top:17px;left:13px;color:var(--muted);pointer-events:none}.input-with-icon .input{padding-left:40px}.login-btn{width:100%;margin-top:12px}.login-error{display:flex;gap:9px;align-items:center;color:var(--ink);background:var(--danger-surface);border-left:4px solid var(--red);padding:12px;font-size:12px;margin-bottom:20px}.login-error svg{flex-shrink:0}.conversation-actions{display:flex;gap:10px;flex-wrap:wrap;align-items:center}.text-chat{padding:24px}.chat-heading{display:flex;align-items:center;gap:14px;flex-wrap:wrap}.chat-heading>div{flex:1;min-width:160px}.chat-heading h2,.chat-heading p{margin:0}.chat-heading p{margin-top:5px}.chat-avatar{flex-shrink:0;object-fit:cover;border:2px solid var(--line);border-radius:0;background:var(--yellow)}.chat-thread{max-height:min(65dvh,640px);min-height:180px;overflow-y:auto;overscroll-behavior:contain;padding:12px 4px}.chat-welcome{max-width:520px;margin:30px auto;text-align:center;line-height:1.7}.chat-welcome h3{font-size:20px}.chat-message{display:flex;align-items:flex-start;gap:12px;margin-bottom:22px}.chat-message.user{justify-content:flex-end;padding-left:40px}.chat-bubble{min-width:0;max-width:90%;padding:14px 18px;background:var(--paper);border:1px solid var(--rule);overflow-wrap:anywhere}.chat-message.user .chat-bubble{background:var(--yellow);border-color:var(--line)}.chat-bubble .prose{margin:8px 0 0}.chat-author{display:flex;flex-wrap:wrap;gap:8px 18px;align-items:baseline;font-size:12px}.chat-author time{color:var(--muted);font-size:10px}.chat-thinking{display:flex;align-items:center;gap:10px;flex-wrap:wrap}.chat-thinking>.small{flex-basis:100%}.chat-compose{border-top:1px solid var(--rule);padding-top:16px}.chat-compose textarea{width:100%;resize:vertical;min-height:82px}.chat-compose-footer{display:flex;justify-content:space-between;align-items:center;gap:12px;margin-top:10px;flex-wrap:wrap}.chat-refresh{margin-top:14px}.chat-boundary{margin:18px 0 0}@media(max-width:600px){.text-chat{padding:16px}.chat-heading>.btn{width:100%}.chat-message{gap:8px}.chat-message.user{padding-left:24px}.chat-bubble{padding:12px;max-width:100%}.chat-message .chat-avatar{width:30px;height:30px}.conversation-actions{width:100%}.conversation-actions>.btn{flex:1}}.voice-entry{padding:20px 24px}.voice-entry-main{display:flex;align-items:center;gap:18px;flex-wrap:wrap}.voice-entry-main>div:nth-child(2){flex:1;min-width:180px}.voice-entry-main h2{font-size:18px;margin:0}.voice-entry-main p{margin:8px 0 0}.voice-entry-main>.btn{text-decoration:none}.voice-entry-icon{width:46px;height:46px;flex-shrink:0;display:grid;place-items:center;border:2px solid var(--line);background:var(--yellow)}.voice-history{margin-top:18px;font-size:12px}.voice-history>summary{color:var(--muted)}.voice-history-call{border-top:1px solid var(--rule);margin-top:14px;padding-top:12px}.voice-history-turn{border-left:3px solid var(--accent);padding-left:14px;margin:20px 0}.voice-history-turn>p{margin-top:8px}.voice-reconnect{display:flex;align-items:center;flex-wrap:wrap;gap:12px;margin-top:18px}.voice-dialog{width:min(900px,calc(100% - 32px));max-height:calc(100dvh - 32px);margin:auto;padding:26px;color:var(--ink);background:var(--panel);border:2px solid var(--line);box-shadow:8px 8px 0 var(--accent);overscroll-behavior:contain}.voice-dialog::backdrop{background:#111111b3}.voice-dialog-header{display:flex;align-items:center;gap:14px;padding-bottom:18px;border-bottom:2px solid var(--line)}.voice-dialog-header>div{flex:1}.voice-dialog-header h2{margin:12px 0 0;font-size:18px}.voice-clock{font:14px ui-monospace,monospace;font-variant-numeric:tabular-nums}.voice-call-body{--scene-height: clamp(280px, 46dvh, 460px);margin-top:18px}.voice-preparation{padding:20px;border:2px solid var(--line)}.voice-scene{position:relative;isolation:isolate;min-width:0;height:var(--scene-height);overflow:hidden}.voice-scene-poster{display:block;width:100%;height:100%;object-fit:cover;border:2px solid var(--line)}.voice-captions{position:absolute;z-index:1;inset:auto 2px 2px;padding:32px 18px 16px;color:#fff;background:linear-gradient(transparent,#000000c7);text-align:center;font-size:clamp(16px,1.8vw,21px);line-height:1.5;text-shadow:0 1px 3px #000;pointer-events:none}.voice-caption-speaker{display:block;font-size:11px;font-weight:800;letter-spacing:.08em;margin-bottom:3px}.voice-caption-window{display:flex;align-items:flex-end;justify-content:center;max-height:4.5em;overflow:hidden}.voice-caption-window p{margin:0;min-width:0;max-width:70ch;overflow-wrap:anywhere}.voice-captions[data-kind=status]{font-style:italic}.voice-conversation{margin-top:14px;border-top:1px solid var(--rule);padding-top:12px;font-size:12px}.voice-conversation>summary{color:var(--muted);cursor:pointer}.voice-call-details{min-width:0;max-height:min(48dvh,440px);overflow-y:auto;padding-right:5px}.voice-answer{overflow-wrap:anywhere}.voice-sources{display:flex;gap:6px;justify-content:flex-start;flex-wrap:wrap;margin-top:18px}.voice-notice{padding:10px 12px;border:1px solid var(--rule)}.voice-source{border:2px solid var(--line);padding:14px;margin:14px 0;font-size:12px;overflow-wrap:anywhere}.voice-source pre{max-height:180px}.voice-controls{display:flex;align-items:stretch;justify-content:center;gap:12px;margin-top:18px}.voice-controls .btn{min-width:0}.btn-danger{color:var(--ink);background:var(--red);border-color:var(--line);box-shadow:3px 3px 0 var(--ink)}.btn-danger:hover:not(:disabled){background:var(--danger-surface)}.is-muted{background:var(--yellow)}.voice-options{display:flex;justify-content:center;flex-wrap:wrap;gap:8px;margin-top:10px}.voice-options .voice-keyboard-toggle{margin:0}.voice-keyboard-toggle{display:flex;align-items:center;gap:8px;margin:auto;padding:8px;border:0;background:transparent;color:var(--muted);font-size:12px}.voice-keyboard-toggle[aria-pressed=true]{background:var(--yellow);color:var(--ink);box-shadow:inset 0 0 0 2px var(--ink)}.voice-compose{display:flex;gap:10px;margin-top:12px}.voice-compose .input{flex:1}.voice-compose .btn{padding:10px;flex-shrink:0}.voice-transcript{font-size:14px;line-height:1.6}.voice-transcript>div{margin-top:18px;overflow-wrap:anywhere}.voice-transcript p{white-space:pre-wrap;overflow-wrap:anywhere;margin-block:8px}.voice-footer{display:flex;justify-content:center;align-items:center;gap:7px;margin-top:20px;color:var(--muted);font-size:10px;line-height:1.6}.voice-footer svg{flex-shrink:0}.brand{color:inherit;text-decoration:none}.sync-home,.sync-detail{width:min(100%,1060px);margin:auto;padding:40px 30px 72px;min-width:0}.sync-detail{width:min(100%,1180px)}.home-hint{max-width:75ch;margin:22px 0}.setup-panel{margin-block:24px;padding:18px;border:2px solid var(--line);background:var(--panel);overflow-wrap:anywhere}.settings-dialog .setup-panel{padding:14px;margin-bottom:0}.setup-panel h2{font-size:18px}.setup-panel p,.setup-panel ul{margin-block:10px}.setup-panel code{font-size:.9em;white-space:normal}.setup-commands{font-size:13px;padding-left:12px;border-left:3px solid var(--accent)}.home-counts{display:flex;flex-wrap:wrap;gap:10px 24px;border-block:2px solid var(--line);padding:15px 0;font-size:12px}.home-counts strong{font-size:20px;margin-right:5px}.sync-feed{display:grid;gap:20px;margin:30px 0}.sync-tile{display:block;min-width:0;padding:20px 24px;margin:0;color:var(--ink);text-decoration:none;box-shadow:8px 8px 0 var(--accent)}.sync-tile:hover{border-color:var(--accent)}.sync-tile-heading{display:flex;gap:12px;align-items:center;margin-bottom:7px}.sync-tile-heading>strong{font-size:17px;text-transform:uppercase}.sync-tile-heading>svg{margin-left:auto;flex-shrink:0}.sync-tile-preview{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;overflow:hidden;max-height:4.5em;line-height:1.5;margin:12px 0 8px;font-size:14px;white-space:pre-line;overflow-wrap:anywhere}.sync-tile-kind{font-size:10px}.sync-cost{display:inline-block}.source-settings{margin-top:35px;padding-top:18px;border-top:1px solid var(--rule)}.source-settings>summary,.detail-section>summary{cursor:pointer;font-weight:800}.agent-source{margin-top:20px;padding-top:16px;border-top:1px solid var(--rule);min-width:0}.agent-source h3{margin:0}.source-session-meta{display:block;margin-block:6px;overflow-wrap:anywhere}.source-warnings{padding-left:20px;overflow-wrap:anywhere}.index-toggle{display:flex;align-items:flex-start;gap:10px;padding:12px;margin-top:14px;border:2px solid var(--line);cursor:pointer;background:var(--paper)}.index-toggle>span{min-width:0}.index-toggle strong,.index-toggle .small{display:block}.back-link{display:inline-flex;align-items:center;gap:8px;color:var(--ink);font-size:12px;margin-bottom:24px}.sync-detail>.page-heading{margin-bottom:28px}.detail-section{border:2px solid var(--line);background:var(--panel);margin:18px 0;padding:18px 22px;min-width:0}.detail-section[open]>summary{margin-bottom:22px}.detail-section .briefing-card,.detail-section .card{box-shadow:none}.memory-recap{padding-block:14px;border-top:1px solid var(--rule)}.memory-recap>a{color:var(--blue);font-weight:800}.detail-footer{display:flex;gap:20px;align-items:center;justify-content:space-between}.sync-detail .working{flex-wrap:wrap}.sync-detail .working .btn{margin-left:auto}@media(max-width:760px){.sync-home,.sync-detail{padding:26px 20px 56px}.sync-home>.page-heading>.btn{width:100%}.sync-tile{padding:16px}.sync-tile .small{font-size:11px}.sync-tile-kind{display:none}.detail-section{padding:16px}.detail-footer{flex-direction:column;align-items:flex-start}.recap-card .section-heading{flex-wrap:wrap}}@media(max-width:1100px){.page-heading{align-items:flex-start;flex-direction:column;gap:20px}}@media(max-width:760px){.header{padding:14px 16px;flex-wrap:wrap}.header-right{gap:10px}.brand strong{font-size:24px}.brand img{width:36px;height:36px}.brand span{font-size:9px}.settings-dialog{--settings-padding: 16px}.session-list{max-height:180px}.notes-grid{grid-template-columns:1fr}.card{padding:20px}.section-heading,.form-footer{flex-wrap:wrap}.form-footer>.btn{margin-left:auto}.tree-browser ul{padding-left:8px}.tree-browser>ul{padding-left:0}.role-label{display:none}.login-card{padding:28px 22px}.voice-entry{padding:18px}.voice-entry-main{gap:12px}.voice-entry-main>.btn{width:100%}.voice-dialog{padding:14px}.voice-dialog-header{gap:10px}.voice-dialog-header .eyebrow{font-size:8px}.voice-controls{gap:8px}.voice-controls .btn{flex:1;flex-direction:column;padding:10px 6px;font-size:10px}.voice-call-body{--scene-height: clamp(200px, 40dvh, 340px);margin-top:12px}.voice-captions{padding:24px 12px 12px;font-size:17px}.voice-footer{margin-top:12px}}.history-progress{padding:14px;margin-block:16px;border:2px solid var(--line);background:var(--panel);text-align:left}.history-progress p{margin-block:8px;overflow-wrap:anywhere}.history-page .card{margin-block:20px}.history-search{margin-block:28px}.history-actions{display:flex;flex-wrap:wrap;gap:16px;align-items:end;margin-block:16px}.history-excerpt{white-space:pre-wrap;overflow-wrap:anywhere;font:inherit;line-height:1.6}.history-source,.history-result{min-width:0;overflow-wrap:anywhere}@media(max-width:540px){.header-right{gap:10px;font-size:12px}.history-actions{align-items:stretch;flex-direction:column}}@media(prefers-reduced-motion:reduce){*,*:before,*:after{transition:none!important;scroll-behavior:auto!important}.spinner{animation:none}}@media(forced-colors:active){body{background-image:none}.btn,.icon-button,.card,.login-card,.evidence{box-shadow:none}.tree-card progress,.history-progress progress{-webkit-appearance:auto;-moz-appearance:auto;appearance:auto}.voice-captions{background:Canvas;color:CanvasText;text-shadow:none}}