openfox 1.6.73 → 1.6.75

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.
@@ -2,7 +2,7 @@ import {
2
2
  maybeAutoCompactContext,
3
3
  performManualContextCompaction,
4
4
  resolveCompactionStatsIdentity
5
- } from "./chunk-ODUSHSK2.js";
5
+ } from "./chunk-ETIXH35K.js";
6
6
  import "./chunk-GQZGIMJO.js";
7
7
  import "./chunk-7JPKRM6M.js";
8
8
  import "./chunk-RBPOAAIZ.js";
@@ -24,4 +24,4 @@ export {
24
24
  performManualContextCompaction,
25
25
  resolveCompactionStatsIdentity
26
26
  };
27
- //# sourceMappingURL=auto-compaction-HQHEK75L.js.map
27
+ //# sourceMappingURL=auto-compaction-OW4P2QWQ.js.map
@@ -8,8 +8,8 @@ import {
8
8
  } from "./chunk-4CQ7CUQ6.js";
9
9
  import {
10
10
  runChatTurn
11
- } from "./chunk-EGIJKK4U.js";
12
- import "./chunk-ODUSHSK2.js";
11
+ } from "./chunk-IA4O65CR.js";
12
+ import "./chunk-ETIXH35K.js";
13
13
  import "./chunk-GQZGIMJO.js";
14
14
  import "./chunk-7JPKRM6M.js";
15
15
  import "./chunk-RBPOAAIZ.js";
@@ -61,7 +61,7 @@ async function startChatSession(sessionId, content, deps, options) {
61
61
  sessionManager.setRunning(sessionId, true);
62
62
  broadcastForSession(sessionId, createSessionRunningMessage(true));
63
63
  try {
64
- const { maybeAutoCompactContext } = await import("./auto-compaction-HQHEK75L.js");
64
+ const { maybeAutoCompactContext } = await import("./auto-compaction-OW4P2QWQ.js");
65
65
  await maybeAutoCompactContext({
66
66
  sessionManager,
67
67
  sessionId,
@@ -170,4 +170,4 @@ export {
170
170
  startChatSession,
171
171
  stopSessionExecution
172
172
  };
173
- //# sourceMappingURL=chat-handler-NNDQSDFI.js.map
173
+ //# sourceMappingURL=chat-handler-KYMMXPP6.js.map
@@ -2075,7 +2075,17 @@ Make sure whitespace and indentation match exactly.`
2075
2075
  newContent: edit.newContent
2076
2076
  }))
2077
2077
  }));
2078
- const replacedContent = replaceAll ? normalizedContent.replaceAll(normalizedOldString, args.new_string) : normalizedContent.replace(normalizedOldString, args.new_string);
2078
+ const normalizedNewString = normalizeToLF(args.new_string);
2079
+ let replacedContent;
2080
+ if (replaceAll) {
2081
+ replacedContent = normalizedContent.replaceAll(normalizedOldString, normalizedNewString);
2082
+ } else {
2083
+ const index = normalizedContent.indexOf(normalizedOldString);
2084
+ if (index === -1) {
2085
+ return helpers.error("old_string not found in file (unexpected)");
2086
+ }
2087
+ replacedContent = normalizedContent.slice(0, index) + normalizedNewString + normalizedContent.slice(index + normalizedOldString.length);
2088
+ }
2079
2089
  const newContent = replacedContent.replace(/\n/g, fileLineEnding === "crlf" ? "\r\n" : fileLineEnding === "cr" ? "\r" : "\n");
2080
2090
  await writeFile3(fullPath, newContent, "utf-8");
2081
2091
  let output = `Successfully replaced ${replaceAll ? occurrences : 1} occurrence(s) in ${args.path}`;
@@ -3381,7 +3391,7 @@ var callSubAgentTool = {
3381
3391
  };
3382
3392
  }
3383
3393
  try {
3384
- const { getToolRegistryForAgent: getToolRegistryForAgent2 } = await import("./tools-5MCH72FH.js");
3394
+ const { getToolRegistryForAgent: getToolRegistryForAgent2 } = await import("./tools-RUAY6EVI.js");
3385
3395
  const toolRegistry = getToolRegistryForAgent2(agentDef);
3386
3396
  const turnMetrics = new TurnMetrics();
3387
3397
  const result = await executeSubAgent({
@@ -4535,4 +4545,4 @@ export {
4535
4545
  getToolRegistryForAgent,
4536
4546
  createToolRegistry
4537
4547
  };
4538
- //# sourceMappingURL=chunk-ODUSHSK2.js.map
4548
+ //# sourceMappingURL=chunk-ETIXH35K.js.map
@@ -13,7 +13,7 @@ import {
13
13
  getToolRegistryForAgent,
14
14
  loadAllAgentsDefault,
15
15
  runTopLevelAgentLoop
16
- } from "./chunk-ODUSHSK2.js";
16
+ } from "./chunk-ETIXH35K.js";
17
17
  import {
18
18
  getCurrentContextWindowId,
19
19
  getEventStore
@@ -295,4 +295,4 @@ export {
295
295
  runBuilderTurn,
296
296
  runVerifierTurn
297
297
  };
298
- //# sourceMappingURL=chunk-EGIJKK4U.js.map
298
+ //# sourceMappingURL=chunk-IA4O65CR.js.map
@@ -190,7 +190,7 @@ async function runCli(options) {
190
190
  if (!configExists) {
191
191
  await runNetworkSetup(mode);
192
192
  }
193
- const { runServe } = await import("./serve-YCFUOOGT.js");
193
+ const { runServe } = await import("./serve-TW63YCNQ.js");
194
194
  await runServe({
195
195
  mode,
196
196
  port: values.port ? parseInt(values.port) : void 0,
@@ -203,4 +203,4 @@ async function runCli(options) {
203
203
  export {
204
204
  runCli
205
205
  };
206
- //# sourceMappingURL=chunk-PPSXSDMY.js.map
206
+ //# sourceMappingURL=chunk-VIGOXEZG.js.map
@@ -2,7 +2,7 @@ import {
2
2
  createVerifierNudgeConfig,
3
3
  runBuilderTurn,
4
4
  runChatTurn
5
- } from "./chunk-EGIJKK4U.js";
5
+ } from "./chunk-IA4O65CR.js";
6
6
  import {
7
7
  TurnMetrics,
8
8
  agentExists,
@@ -37,7 +37,7 @@ import {
37
37
  setSkillEnabled,
38
38
  skillExists,
39
39
  spawnShellProcess
40
- } from "./chunk-ODUSHSK2.js";
40
+ } from "./chunk-ETIXH35K.js";
41
41
  import {
42
42
  getProject
43
43
  } from "./chunk-7JPKRM6M.js";
@@ -5014,7 +5014,7 @@ function createTerminalRoutes() {
5014
5014
  }
5015
5015
 
5016
5016
  // src/constants.ts
5017
- var VERSION = "1.6.73";
5017
+ var VERSION = "1.6.75";
5018
5018
 
5019
5019
  // src/server/index.ts
5020
5020
  var __dirname2 = dirname5(fileURLToPath4(import.meta.url));
@@ -5317,7 +5317,7 @@ async function createServerHandle(config) {
5317
5317
  if (!callId || approved === void 0) {
5318
5318
  return res.status(400).json({ error: "callId and approved are required" });
5319
5319
  }
5320
- const { providePathConfirmation } = await import("./tools-5MCH72FH.js");
5320
+ const { providePathConfirmation } = await import("./tools-RUAY6EVI.js");
5321
5321
  const result = providePathConfirmation(callId, approved, alwaysAllow);
5322
5322
  if (!result.found) {
5323
5323
  return res.status(404).json({ error: "No pending path confirmation with that ID" });
@@ -5341,7 +5341,7 @@ async function createServerHandle(config) {
5341
5341
  if (!callId || !answer) {
5342
5342
  return res.status(400).json({ error: "callId and answer are required" });
5343
5343
  }
5344
- const { provideAnswer: provideAnswer2 } = await import("./tools-5MCH72FH.js");
5344
+ const { provideAnswer: provideAnswer2 } = await import("./tools-RUAY6EVI.js");
5345
5345
  const found = provideAnswer2(callId, answer);
5346
5346
  if (!found) {
5347
5347
  return res.status(404).json({ error: "No pending question with that ID" });
@@ -5377,8 +5377,8 @@ async function createServerHandle(config) {
5377
5377
  if (!session) {
5378
5378
  return res.status(404).json({ error: "Session not found" });
5379
5379
  }
5380
- const { stopSessionExecution } = await import("./chat-handler-NNDQSDFI.js");
5381
- const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-5MCH72FH.js");
5380
+ const { stopSessionExecution } = await import("./chat-handler-KYMMXPP6.js");
5381
+ const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-RUAY6EVI.js");
5382
5382
  stopSessionExecution(sessionId, sessionManager);
5383
5383
  abortSession(sessionId);
5384
5384
  cancelQuestionsForSession(sessionId, "Session stopped by user");
@@ -5852,7 +5852,7 @@ async function createServerHandle(config) {
5852
5852
  providerManager
5853
5853
  );
5854
5854
  const wss = wssExports.wss;
5855
- const { QueueProcessor } = await import("./processor-HF5SS6CR.js");
5855
+ const { QueueProcessor } = await import("./processor-23O4HPSS.js");
5856
5856
  const queueProcessor = new QueueProcessor({
5857
5857
  sessionManager,
5858
5858
  providerManager,
@@ -5927,4 +5927,4 @@ export {
5927
5927
  createServerHandle,
5928
5928
  createServer
5929
5929
  };
5930
- //# sourceMappingURL=chunk-RTOWT3GF.js.map
5930
+ //# sourceMappingURL=chunk-XIZ6B6IS.js.map
package/dist/cli/dev.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runCli
4
- } from "../chunk-PPSXSDMY.js";
4
+ } from "../chunk-VIGOXEZG.js";
5
5
  import {
6
6
  logger
7
7
  } from "../chunk-PNBH3RAX.js";
package/dist/cli/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runCli
4
- } from "../chunk-PPSXSDMY.js";
4
+ } from "../chunk-VIGOXEZG.js";
5
5
  import {
6
6
  logger
7
7
  } from "../chunk-PNBH3RAX.js";
@@ -3,7 +3,7 @@ import {
3
3
  runBuilderTurn,
4
4
  runChatTurn,
5
5
  runVerifierTurn
6
- } from "./chunk-EGIJKK4U.js";
6
+ } from "./chunk-IA4O65CR.js";
7
7
  import {
8
8
  TurnMetrics,
9
9
  createChatDoneEvent,
@@ -11,7 +11,7 @@ import {
11
11
  createMessageStartEvent,
12
12
  createToolCallEvent,
13
13
  createToolResultEvent
14
- } from "./chunk-ODUSHSK2.js";
14
+ } from "./chunk-ETIXH35K.js";
15
15
  import "./chunk-GQZGIMJO.js";
16
16
  import "./chunk-7JPKRM6M.js";
17
17
  import "./chunk-RBPOAAIZ.js";
@@ -40,4 +40,4 @@ export {
40
40
  runChatTurn,
41
41
  runVerifierTurn
42
42
  };
43
- //# sourceMappingURL=orchestrator-T2EQZJS5.js.map
43
+ //# sourceMappingURL=orchestrator-QP4O7MUM.js.map
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openfox",
3
- "version": "1.6.73",
3
+ "version": "1.6.75",
4
4
  "description": "Local-LLM-first agentic coding assistant",
5
5
  "type": "module",
6
6
  "bin": {
@@ -173,7 +173,7 @@ var QueueProcessor = class {
173
173
  backend: provider?.backend ?? llmClient.getBackend(),
174
174
  model: llmClient.getModel()
175
175
  };
176
- const { runChatTurn } = await import("./orchestrator-T2EQZJS5.js");
176
+ const { runChatTurn } = await import("./orchestrator-QP4O7MUM.js");
177
177
  const runChatTurnParams = buildRunChatTurnParams({
178
178
  sessionManager,
179
179
  sessionId,
@@ -210,4 +210,4 @@ var QueueProcessor = class {
210
210
  export {
211
211
  QueueProcessor
212
212
  };
213
- //# sourceMappingURL=processor-HF5SS6CR.js.map
213
+ //# sourceMappingURL=processor-23O4HPSS.js.map
@@ -6,9 +6,9 @@ import {
6
6
  import {
7
7
  VERSION,
8
8
  createServer
9
- } from "./chunk-RTOWT3GF.js";
10
- import "./chunk-EGIJKK4U.js";
11
- import "./chunk-ODUSHSK2.js";
9
+ } from "./chunk-XIZ6B6IS.js";
10
+ import "./chunk-IA4O65CR.js";
11
+ import "./chunk-ETIXH35K.js";
12
12
  import "./chunk-GQZGIMJO.js";
13
13
  import "./chunk-7JPKRM6M.js";
14
14
  import "./chunk-RBPOAAIZ.js";
@@ -188,4 +188,4 @@ async function runServe(options) {
188
188
  export {
189
189
  runServe
190
190
  };
191
- //# sourceMappingURL=serve-YCFUOOGT.js.map
191
+ //# sourceMappingURL=serve-TW63YCNQ.js.map
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  createServer,
3
3
  createServerHandle
4
- } from "../chunk-RTOWT3GF.js";
5
- import "../chunk-EGIJKK4U.js";
6
- import "../chunk-ODUSHSK2.js";
4
+ } from "../chunk-XIZ6B6IS.js";
5
+ import "../chunk-IA4O65CR.js";
6
+ import "../chunk-ETIXH35K.js";
7
7
  import "../chunk-GQZGIMJO.js";
8
8
  import "../chunk-7JPKRM6M.js";
9
9
  import "../chunk-RBPOAAIZ.js";
@@ -11,7 +11,7 @@ import {
11
11
  requestPathAccess,
12
12
  stepDoneTool,
13
13
  validateToolAction
14
- } from "./chunk-ODUSHSK2.js";
14
+ } from "./chunk-ETIXH35K.js";
15
15
  import "./chunk-GQZGIMJO.js";
16
16
  import "./chunk-7JPKRM6M.js";
17
17
  import "./chunk-RBPOAAIZ.js";
@@ -49,4 +49,4 @@ export {
49
49
  stepDoneTool,
50
50
  validateToolAction
51
51
  };
52
- //# sourceMappingURL=tools-5MCH72FH.js.map
52
+ //# sourceMappingURL=tools-RUAY6EVI.js.map
@@ -81,7 +81,7 @@ WARNING: This link could potentially be dangerous`)){const b=window.open();if(b)
81
81
  w-[300px] bg-secondary border-r border-border flex flex-col
82
82
  transition-all duration-300 ease-in-out
83
83
  ${r?"translate-x-0":"-translate-x-full"}
84
- `,children:[o.jsxs("div",{className:"p-4 border-b border-border flex gap-2",children:[o.jsx(Fn,{href:`/p/${e}/new`,className:"flex-1 block text-center rounded font-medium transition-colors bg-accent-primary/25 text-text-primary hover:bg-accent-primary/40 px-3 py-1.5 text-sm","data-testid":"sidebar-new-session-button",children:"+ New Session"}),o.jsx(bo,{items:[{label:"Edit project settings",onClick:()=>u(!0)},{label:"Delete all sessions",onClick:_,danger:!0}],trigger:o.jsx("button",{className:"flex-shrink-0 p-2.5 rounded hover:bg-bg-tertiary text-text-muted hover:text-text-primary transition-colors",title:"Options",children:o.jsx(Bh,{})})}),s&&o.jsx(lo,{onClick:s,className:"md:hidden",variant:"sidebar",size:"md"})]}),k&&o.jsx(hC,{isOpen:c,onClose:()=>u(!1),project:k}),o.jsx("div",{className:"flex-1 overflow-y-auto",children:b.length===0?o.jsx("div",{className:"p-4 text-center text-text-muted text-xs",children:"No sessions"}):o.jsxs(o.Fragment,{children:[o.jsx("div",{className:"divide-y divide-border",children:mC(b,l,d,x,e)}),S&&o.jsx("div",{className:"p-4 text-center text-text-muted text-xs",children:"Loading more..."}),o.jsx("div",{ref:C,className:"h-px"})]})})]})]})}function mC(e,r,s,i,c){const u=iy(e);return Array.from(u).map(([h,l])=>{const d=l[0];return d?o.jsxs("div",{children:[o.jsx("div",{className:"px-4 py-2 bg-bg-tertiary/30 text-text-muted text-xs font-medium",children:ry(d.updatedAt)}),l.map(f=>{const g=(r==null?void 0:r.id)===f.id,m=s.includes(f.id),v=f.isRunning;return o.jsx("div",{className:`w-full px-4 py-3 text-left hover:bg-bg-tertiary/50 transition-colors group ${g?"bg-bg-tertiary":""}`,children:o.jsxs(Fn,{href:`/p/${c}/s/${f.id}`,className:`block ${g?"text-accent-primary":"text-text-primary"} hover:text-accent-primary`,children:[o.jsxs("div",{className:"flex justify-between items-center mb-1",children:[o.jsx("span",{className:`font-medium truncate text-sm ${g?"text-accent-primary":"text-text-primary"}`,children:f.title??f.id.slice(0,6)}),o.jsx(bo,{items:[{label:"Delete session",onClick:S=>i(f.id,S),danger:!0}],trigger:o.jsx("button",{onClick:S=>S.preventDefault(),className:"p-1.5 rounded hover:bg-bg-tertiary text-text-muted hover:text-text-primary transition-all",title:"Options",children:o.jsx(Bh,{})})})]}),o.jsxs("div",{className:"flex items-center gap-2 mt-1",children:[v?o.jsx(Nw,{}):m&&!g?o.jsx("span",{"aria-label":"Unread activity",title:"Unread activity",className:"w-2 h-2 rounded-full bg-amber-400 flex-shrink-0"}):null,o.jsx("span",{className:"text-text-muted text-xs flex-shrink-0",children:uc(f.updatedAt)}),o.jsxs("span",{className:"text-text-muted text-xs flex-shrink-0",children:[f.messageCount," messages"]})]})]})},f.id)})]},h):null})}const ab=["⠋","⠙","⠹","⠸","⠼","⠴"];function gC(){var l;const e=Ft(d=>d.currentProject),r=Ce(d=>d.currentSession),s=qv(),i=!1,c=P.useRef(0),u=P.useRef(null);P.useEffect(()=>(s?(u.current=window.setInterval(()=>{c.current=(c.current+1)%ab.length,h()},150),h()):(u.current&&(clearInterval(u.current),u.current=null),h()),()=>{u.current&&(clearInterval(u.current),u.current=null)}),[s,e,r,i]);const h=()=>{var m;const f=(m=r==null?void 0:r.metadata)==null?void 0:m.title,g=s?`${ab[c.current]} `:"";e&&f?document.title=`${g}${e.name} - ${f} | OpenFox`:e?document.title=`${g}${e.name} | OpenFox`:document.title=`${g}OpenFox`};return typeof window<"u"&&((l=r==null?void 0:r.metadata)!=null&&l.title)&&window.document.documentElement.setAttribute("data-session-title",r.metadata.title),null}function xC({isOpen:e,onClose:r,projectName:s,onConfirm:i}){const c=()=>{i(),r()};return o.jsx(At,{isOpen:e,onClose:r,title:"Delete Project",size:"sm",children:o.jsxs("div",{className:"space-y-4",children:[o.jsxs("p",{className:"text-text-secondary",children:["This will permanently delete the project ",o.jsx("span",{className:"font-semibold text-text-primary",children:s})," and all its sessions from OpenFox. The project files on disk will remain untouched."]}),o.jsxs("div",{className:"flex justify-end gap-2",children:[o.jsx(nt,{variant:"secondary",onClick:r,children:"Cancel"}),o.jsx(nt,{variant:"danger",onClick:c,children:"Delete"})]})]})})}const dc=P.forwardRef(({className:e="",...r},s)=>o.jsx("input",{ref:s,className:`bg-bg-tertiary border border-border rounded px-3 py-2 text-text-primary placeholder-text-muted focus:outline-none focus:ring-2 focus:ring-accent-primary/50 focus:border-accent-primary ${e}`,...r}));dc.displayName="Input";function bC(e){return!e||e.trim()===""?{valid:!1,error:"Project name cannot be empty"}:/^[a-zA-Z0-9._-]+$/.test(e)?{valid:!0}:{valid:!1,error:"Project name can only contain letters, numbers, hyphens, underscores, and dots"}}function vC({isOpen:e,onClose:r}){const[,s]=lr(),[i,c]=P.useState(""),[u,h]=P.useState(null),[l,d]=P.useState(!1),[f,g]=P.useState(""),m=P.useRef(null);P.useEffect(()=>{e&&(ke("/api/config").then(C=>C.json()).then(C=>{C.workdir&&g(C.workdir)}),c(""),h(null),d(!1),setTimeout(()=>{var C;(C=m.current)==null||C.focus()},100))},[e]);const v=P.useCallback(async C=>{C.preventDefault();const y=bC(i);if(!y.valid){h(y.error);return}d(!0),h(null);const b=`${f}/${i}`;try{const x=await ke("/api/projects",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:i,workdir:b})});if(!x.ok){const A=await x.json().catch(()=>({}));throw new Error(A.error||"Failed to create project")}const j=(await x.json()).project;r(),s(`/p/${j.id}`)}catch(x){h(x instanceof Error?x.message:"Failed to create project"),d(!1)}},[i,s,r,f]),S=P.useCallback(()=>{c(""),h(null),r()},[r]),k=i?`${f}/${i}`:"";return o.jsx(At,{isOpen:e,onClose:S,title:"Create New Project",size:"sm",children:o.jsxs("form",{onSubmit:v,className:"space-y-4",children:[o.jsxs("div",{children:[o.jsx("label",{htmlFor:"project-name",className:"block text-sm font-medium text-text-secondary mb-2",children:"Project Name"}),o.jsx(dc,{ref:m,id:"project-name",value:i,onChange:C=>{c(C.target.value),h(null)},placeholder:"my-project",disabled:l,"data-testid":"create-project-name-input",className:"w-full"}),i&&o.jsxs("div",{className:"mt-2 text-xs text-text-muted",children:["Full path: ",o.jsx("span",{className:"font-mono",children:k})]}),u&&o.jsx("div",{className:"mt-3 p-3 bg-accent-error/10 border border-accent-error/30 rounded text-sm text-accent-error",children:u})]}),o.jsxs("div",{className:"flex justify-end gap-2",children:[o.jsx(nt,{type:"button",variant:"secondary",onClick:S,disabled:l,children:"Cancel"}),o.jsx(nt,{type:"submit",variant:"primary",disabled:l||!i.trim(),"data-testid":"create-project-submit-button",className:"min-w-[100px]",children:l?o.jsxs("span",{className:"flex items-center gap-2",children:[o.jsx(qi,{className:"h-4 w-4"}),"Creating..."]}):"Create"})]})]})})}const yC={sm:"w-4 h-4",md:"w-8 h-8",lg:"w-12 h-12"};function vo({size:e="md",className:r=""}){return o.jsx("div",{className:`animate-spin border-2 border-accent-primary border-t-transparent rounded-full ${yC[e]} ${r}`})}function _C({text:e,...r}){return o.jsxs("div",{className:"text-center",children:[o.jsx(vo,{...r,className:"mx-auto mb-4"}),e&&o.jsx("div",{className:"text-text-secondary",children:e})]})}function oy({onSelect:e,onClose:r,initialPath:s}){const[i,c]=P.useState(null),[u,h]=P.useState(!0),[l,d]=P.useState(""),[f,g]=P.useState(-1),m=P.useRef(null),v=P.useRef([]),S=P.useCallback(async x=>{h(!0),d(""),g(-1);try{const _=x?`/api/directories?path=${encodeURIComponent(x)}`:"/api/directories",A=await(await ke(_)).json();c(A)}catch(_){console.error("Failed to load directories:",_)}finally{h(!1)}},[]);P.useEffect(()=>{S(s)},[s,S]);const k=((i==null?void 0:i.current)??"").split("/").filter(Boolean).map((x,_,j)=>({name:x,path:"/"+j.slice(0,_+1).join("/")})),C=(i==null?void 0:i.directories.filter(x=>l===""||x.name.toLowerCase().includes(l.toLowerCase())))??[],y=[...i!=null&&i.parent?[{type:"parent",path:i.parent,name:".."}]:[],...C.map(x=>({type:"dir",path:x.path,name:x.name}))];P.useEffect(()=>{g(l?0:-1)},[l,C.length]),P.useEffect(()=>{var x;f>=0&&v.current[f]&&((x=v.current[f])==null||x.scrollIntoView({block:"nearest"}))},[f]);const b=x=>{var _;if(x.key==="ArrowDown")x.preventDefault(),g(j=>Math.min(j+1,y.length-1));else if(x.key==="ArrowUp")x.preventDefault(),g(j=>Math.max(j-1,0));else if(x.key==="Enter"){if(x.preventDefault(),f>=0&&y[f]){const j=y[f];j.type,S(j.path)}}else x.key==="Escape"&&(d(""),(_=m.current)==null||_.focus())};return o.jsxs(At,{isOpen:!0,onClose:r,title:"Select Folder",size:"lg",children:[i&&o.jsx("div",{className:"px-3 py-2 bg-bg-tertiary/30 -mx-4 -mt-4 mb-4 border-b border-border",children:o.jsxs("div",{className:"flex items-center text-xs overflow-x-auto",children:[k.map((x,_)=>o.jsxs("span",{className:"flex items-center shrink-0",children:[o.jsx("span",{className:"text-text-muted",children:"/"}),o.jsx("button",{onClick:()=>S(x.path),className:`px-1 ${_===k.length-1?"text-accent-primary font-medium":"text-text-secondary hover:text-accent-primary"}`,children:x.name})]},x.path)),k.length===0&&o.jsx("button",{onClick:()=>S("/"),className:"text-text-muted hover:text-accent-primary",children:"/"})]})}),o.jsx("div",{className:"px-4 mb-3",children:o.jsxs("div",{className:"relative",children:[o.jsx("span",{className:"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-text-muted pointer-events-none flex items-center justify-center",children:o.jsx(Hh,{})}),o.jsx(dc,{autoFocus:!0,ref:m,value:l,onChange:x=>d(x.target.value),onKeyDown:b,placeholder:"Filter directories...",className:"w-full pl-9"})]})}),o.jsx("div",{className:"flex-1 overflow-y-auto -mx-4",children:u?o.jsx("div",{className:"p-8 text-center",children:o.jsx(vo,{size:"sm"})}):y.length===0?o.jsx("div",{className:"p-8 text-center text-text-muted text-sm",children:l?"No matching directories":"No subdirectories"}):o.jsx("div",{className:"divide-y divide-border",children:y.map((x,_)=>o.jsxs("button",{ref:j=>{v.current[_]=j},onClick:()=>S(x.path),onDoubleClick:()=>e(x.path),className:`w-full p-3 flex items-center gap-3 text-left transition-colors ${_===f?"bg-accent-primary/20 text-accent-primary":"hover:bg-bg-tertiary/50"}`,children:[x.type==="parent"?o.jsx(hw,{className:"w-5 h-5 text-text-muted"}):o.jsx(zh,{className:"w-5 h-5"}),o.jsx("span",{className:"flex-1",children:x.name}),_===f&&o.jsx("span",{className:"text-xs text-text-muted",children:"⏎ navigate · dbl-click select"})]},x.path))})}),o.jsxs("div",{className:"flex flex-col gap-2 pt-4 border-t border-border mt-4 -mx-4 -mb-4 p-4",children:[(i==null?void 0:i.current)&&o.jsx("button",{onClick:()=>e(i.current),className:"w-full px-4 py-2 bg-accent-primary text-text-primary rounded-lg font-medium hover:bg-accent-primary/90 transition-colors",children:"Select this folder"}),o.jsx("button",{onClick:r,className:"w-full text-center text-text-muted hover:text-text-secondary text-sm",children:"Cancel"})]})]})}function SC({isOpen:e,onClose:r}){const[,s]=lr(),[i,c]=P.useState(!1),[u,h]=P.useState(null),[l,d]=P.useState(!1),f=Ft(N=>N.projects),g=Ft(N=>N.createProject),m=Ft(N=>N.listProjects),v=Ft(N=>N.deleteProject),[S,k]=P.useState(null),[C,y]=P.useState(null),b=(N,D=32)=>{if(N.length<=D)return N;const T=N.split("/").filter(Boolean);if(T.length<=2)return N;const z=T[0],O=T[T.length-1],q=T.slice(1,-1).join("/"),V=D-z.length-O.length-3;if(V<0)return N;const W=q.slice(0,Math.floor(V/2)),I=q.slice(-Math.ceil(V/2));return`/${z}/${W}...${I}/${O}`};P.useEffect(()=>{ke("/api/config").then(N=>N.json()).then(N=>{N.workdir&&h(N.workdir)})},[]),P.useEffect(()=>{e&&m()},[e,m]);const x=N=>{s(`/p/${N}`),r()},_=(N,D)=>{D.stopPropagation(),k(N)},j=()=>{S&&(v(S.id),k(null))},A=N=>{const D=N.split("/").filter(Boolean).pop()??"";g(D,N),m(),y(N)};return P.useEffect(()=>{if(C){const N=f.find(D=>D.workdir===C);N&&(s(`/p/${N.id}`),r(),y(null))}},[f,C,s,r]),e?o.jsxs(At,{isOpen:e,onClose:r,title:"Open Project",size:"xl",footer:o.jsx("div",{className:"flex justify-end gap-2",children:o.jsx(nt,{variant:"secondary",onClick:r,children:"Close"})}),children:[o.jsxs("div",{className:"flex flex-col sm:flex-row flex-1 -m-4",children:[o.jsxs("div",{className:"w-full sm:w-1/2 border-b sm:border-b-0 sm:border-r border-border flex flex-col max-h-[40vh] sm:max-h-[50vh]",children:[o.jsx("div",{className:"p-3 border-b border-border bg-bg-tertiary/30 shrink-0",children:o.jsx("h3",{className:"font-medium text-sm text-text-secondary",children:"Recent Projects"})}),o.jsx("div",{className:"flex-1 overflow-y-auto",children:f.length===0?o.jsxs("div",{className:"p-6 text-center text-text-muted text-sm",children:[o.jsx("p",{className:"mb-2",children:"No recent projects"}),o.jsx("p",{className:"text-xs",children:'Click "Create new project" to add one'})]}):o.jsx("div",{className:"divide-y divide-border",children:f.map(N=>o.jsxs("div",{className:"group flex items-center gap-3 p-3 hover:bg-bg-tertiary/50 transition-colors",children:[o.jsxs("button",{onClick:()=>x(N.id),className:"flex-1 flex items-center gap-3 text-left",children:[o.jsx(zh,{className:"w-5 h-5 text-accent-primary"}),o.jsxs("div",{className:"flex-1 min-w-0",children:[o.jsx("div",{className:"font-medium truncate",children:N.name}),o.jsx("div",{className:"text-xs text-text-muted truncate",children:b(N.workdir)})]})]}),o.jsx("button",{onClick:D=>_(N,D),className:"text-accent-error/70 hover:text-accent-error p-1",title:"Delete project",children:o.jsx(Ph,{className:"w-4 h-4"})})]},N.id))})})]}),o.jsx("div",{className:"w-full sm:w-1/2 flex flex-col items-center justify-center p-6 sm:p-8 text-center",children:o.jsxs("div",{className:"flex flex-col gap-3 w-full max-w-sm",children:[o.jsx(nt,{variant:"primary",onClick:()=>d(!0),children:"Select existing project"}),o.jsx(nt,{variant:"secondary",onClick:()=>c(!0),"data-testid":"open-project-create-button",children:"Create new project"})]})})]}),i&&o.jsx(vC,{isOpen:i,onClose:()=>c(!1)}),S&&o.jsx(xC,{isOpen:!0,onClose:()=>k(null),projectName:S.name,onConfirm:j}),l&&o.jsx(oy,{initialPath:u??void 0,onSelect:N=>{A(N),d(!1)},onClose:()=>d(!1)})]}):null}function wC(){const[e,r]=P.useState(!1),s=Ce(m=>m.sessions),i=Ft(m=>m.projects),c=Ft(m=>m.loading),u=Ft(m=>m.listProjects),h=Ce(m=>m.listSessions),l=Ce(m=>m.connectionStatus);P.useEffect(()=>{l==="connected"&&(u(),h())},[l,u,h]);const d=[...i].sort((m,v)=>{const S=s.filter(b=>b.workdir.startsWith(m.workdir)),k=s.filter(b=>b.workdir.startsWith(v.workdir)),C=S.length>0?new Date(S.reduce((b,x)=>new Date(x.updatedAt)>new Date(b.updatedAt)?x:b).updatedAt).getTime():new Date(m.updatedAt).getTime();return(k.length>0?new Date(k.reduce((b,x)=>new Date(x.updatedAt)>new Date(b.updatedAt)?x:b).updatedAt).getTime():new Date(v.updatedAt).getTime())-C}),f=m=>{const v=i.find(S=>S.id===m);return v?s.filter(S=>S.workdir.startsWith(v.workdir)).sort((S,k)=>new Date(k.updatedAt).getTime()-new Date(S.updatedAt).getTime()).slice(0,5):[]},g=()=>{r(!0)};return o.jsxs("div",{className:"flex-1 flex flex-col overflow-y-auto bg-primary",children:[o.jsxs("div",{className:"max-w-5xl mx-auto w-full p-4 md:p-8",children:[o.jsxs("div",{className:"mb-6 md:mb-8 flex items-center justify-between",children:[o.jsxs("div",{children:[o.jsx("h1",{className:"text-3xl font-bold text-accent-primary",children:"OpenFox"}),o.jsx("p",{className:"text-text-secondary",children:"Local LLM-powered coding assistant with contract-driven execution"})]}),o.jsx(nt,{variant:"primary",onClick:g,children:"Open Project"})]}),d.map(m=>{const v=f(m.id);return o.jsx("div",{className:"mb-6 md:mb-8",children:o.jsxs("div",{className:"bg-bg-secondary border border-border rounded-lg overflow-hidden",children:[o.jsxs("div",{className:"p-3 md:p-4 border-b border-border flex items-center justify-between gap-2",children:[o.jsxs(Fn,{href:`/p/${m.id}`,className:"flex items-center gap-2 cursor-pointer hover:opacity-80 transition-opacity flex-1",children:[o.jsx(zh,{className:"w-5 h-5 text-accent-primary flex-shrink-0"}),o.jsx("span",{className:"text-text-primary font-semibold",children:m.name})]}),o.jsx(Fn,{href:`/p/${m.id}/new`,className:"rounded font-medium transition-colors bg-accent-primary/25 text-text-primary hover:bg-accent-primary/40 px-1.5 py-1 text-xs",children:"+ New Session"})]}),o.jsx("div",{className:"divide-y divide-border",children:v.length>0?v.map(S=>{const k=i.find(y=>S.workdir.startsWith(y.workdir)),C=k?`/p/${k.id}/s/${S.id}`:"#";return o.jsx(Fn,{href:C,className:"block p-3 md:p-4 hover:bg-bg-tertiary/50 cursor-pointer transition-colors",children:o.jsxs("div",{className:"flex items-center justify-between gap-2",children:[o.jsx("div",{className:"flex items-center gap-3 flex-1 min-w-0",children:o.jsx("div",{className:"flex-1 min-w-0",children:o.jsx("div",{className:"text-sm text-text-muted truncate",children:S.title??S.id.slice(0,8)})})}),o.jsxs("div",{className:"flex items-center gap-2 flex-shrink-0",children:[o.jsx("span",{className:"text-text-muted text-xs",children:sC(S.updatedAt)}),o.jsxs("span",{className:"text-text-muted text-xs",children:[S.messageCount," msgs"]})]})]})},S.id)}):o.jsx("div",{className:"p-3 md:p-4 text-text-muted text-sm",children:"No sessions yet"})})]})},m.id)}),d.length===0&&!c&&o.jsx("div",{className:"text-center py-12 text-text-muted",children:"No projects yet. Open a project to get started."}),c&&o.jsx("div",{className:"flex justify-center py-12",children:o.jsx(vo,{})})]}),e&&o.jsx(SC,{isOpen:e,onClose:()=>r(!1)})]})}function CC(){const[,e]=Mh("/p/:projectId/new"),[,r]=lr(),s=e==null?void 0:e.projectId,i=Ce(c=>c.createSession);return P.useEffect(()=>{s&&(async()=>{const u=await i(s);r(u?`/p/${s}/s/${u.id}`:`/p/${s}`)})()},[s,i,r]),o.jsx("div",{className:"flex-1 flex items-center justify-center",children:o.jsx(vo,{})})}function kC(){const e=Ft(r=>r.currentProject);return o.jsx("div",{className:"h-full flex flex-col items-center justify-center p-8 text-center",children:o.jsxs("div",{className:"max-w-md",children:[o.jsx("h2",{className:"text-xl font-semibold text-text-primary mb-2",children:(e==null?void 0:e.name)??"Project"}),o.jsx("p",{className:"text-text-secondary mb-6",children:"No session selected"}),o.jsxs("div",{className:"flex flex-col gap-3",children:[e&&o.jsx(Fn,{href:`/p/${e.id}/new`,"data-testid":"create-new-session-button",className:"block w-full rounded font-medium transition-colors bg-accent-primary/25 text-text-primary hover:bg-accent-primary/40 px-3 py-2 text-center",children:"Create New Session"}),o.jsx("p",{className:"text-sm text-text-muted",children:"Or select an existing session from the sidebar"})]})]})})}const Ga=e=>Math.round(e*10)/10;function mh(e){return{providerId:e.providerId,providerName:e.providerName,backend:e.backend,model:e.model}}function EC(e){return`${e.providerId}::${e.model}`}function jC(e){return`${e.providerName} > ${e.model}`}function ob(e){let r=0,s=0,i=0,c=0,u=0,h=0;const l=[],d=[];let f=0;for(const[v,S]of e.entries()){const k=S.stats,C=mh(k);r+=k.totalTime,s+=k.toolTime,i+=k.prefillTokens,c+=k.generationTokens;const y=k.prefillSpeed>0?k.prefillTokens/k.prefillSpeed:0,b=k.generationSpeed>0?k.generationTokens/k.generationSpeed:0;u+=y,h+=b,l.push({messageId:S.id,timestamp:S.timestamp,...C,mode:k.mode,responseIndex:v+1,prefillTokens:k.prefillTokens,generationTokens:k.generationTokens,prefillSpeed:k.prefillSpeed,generationSpeed:k.generationSpeed,totalTime:k.totalTime,aiTime:k.totalTime-k.toolTime,toolTime:k.toolTime});const x=k.llmCalls??[];for(const _ of x)f+=1,d.push({messageId:S.id,timestamp:_.timestamp??S.timestamp,providerId:_.providerId,providerName:_.providerName,backend:_.backend,model:_.model,mode:k.mode,responseIndex:v+1,sessionCallIndex:f,callIndex:_.callIndex,promptTokens:_.promptTokens,completionTokens:_.completionTokens,ttft:_.ttft,completionTime:_.completionTime,prefillSpeed:_.prefillSpeed,generationSpeed:_.generationSpeed,totalTime:_.totalTime,..._.temperature!==void 0&&{temperature:_.temperature},..._.topP!==void 0&&{topP:_.topP},..._.topK!==void 0&&{topK:_.topK},..._.maxTokens!==void 0&&{maxTokens:_.maxTokens}})}const g=u>0?Ga(i/u):0,m=h>0?Ga(c/h):0;return{totalTime:Ga(r),aiTime:Ga(r-s),toolTime:Ga(s),prefillTokens:i,generationTokens:c,avgPrefillSpeed:g,avgGenerationSpeed:m,responseCount:e.length,llmCallCount:d.length,dataPoints:l,callDataPoints:d}}function NC(e){const r=e.filter(c=>c.stats!==void 0&&c.stats!==null).sort((c,u)=>new Date(c.timestamp).getTime()-new Date(u.timestamp).getTime());if(r.length===0)return null;const s=new Map;for(const c of r){const u=EC(mh(c.stats)),h=s.get(u)??[];s.set(u,[...h,c])}const i=Array.from(s.entries()).map(([c,u])=>{const h=mh(u[0].stats),l=ob(u);return{...h,key:c,label:jC(h),...l}});return{...ob(r),modelGroups:i}}function TC(e){return P.useMemo(()=>NC(e),[e])}function AC(e){const[r,s]=P.useState(null),[i,c]=P.useState(!0),[u,h]=P.useState(null),l=e||"";return P.useEffect(()=>{if(!l){c(!1);return}let d=!0,f=null;const g=async()=>{try{const v=await(await ke(`/api/branch?workdir=${encodeURIComponent(l)}`)).json();d&&(s(v.branch),h(v.error||null),c(!1))}catch(m){d&&(h(m instanceof Error?m.message:"Failed to fetch branch"),c(!1))}};return g(),f=setInterval(g,3e3),()=>{d=!1,f&&clearInterval(f)}},[l]),{branch:r,loading:i,error:u}}function Zl(e){return e.toLocaleString("en-US").replace(/,/g," ")}function lb(e){return e>=1e3?`${(e/1e3).toFixed(1)}k`:e.toFixed(1)}function DC(e){if(e<60)return`${e.toFixed(1)}s`;const r=Math.floor(e/60),s=Math.round(e%60);return`${r}m${s}s`}const cb=["▁","▂","▃","▄","▅","▆","▇","█"];function RC(e,r,s){if(s===r)return 4;const i=(e-r)/(s-r);return Math.min(7,Math.max(0,Math.round(i*7)))}function LC(e,r){if(e===r){const c=Math.max(Math.abs(e)*.05,1);return{minY:e-c,maxY:r+c}}const s=r-e,i=Math.max(s*.1,.1);return{minY:e-i,maxY:r+i}}function OC(e,r){if(e.length===0||r<=0)return{blocks:"",minX:0,maxX:0,minY:0,maxY:0};const s=[...e].sort((m,v)=>m.x-v.x),i=s[0].x,c=s[s.length-1].x,u=Math.min(...s.map(m=>m.y)),h=Math.max(...s.map(m=>m.y)),{minY:l,maxY:d}=LC(u,h),f=Array.from({length:r},()=>" "),g=new Map;for(const m of s){const v=c===i?0:Math.round((m.x-i)/(c-i)*(r-1)),S=g.get(v)??[];g.set(v,[...S,m.y])}for(const[m,v]of g){const S=Math.max(...v);f[m]=cb[RC(S,l,d)]??cb[0]}return{blocks:f.join(""),minX:i,maxX:c,minY:l,maxY:d}}function ub(e){return e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${(e/1e3).toFixed(1)}k`:e.toFixed(1)}function db({data:e,width:r=60,height:s=78,label:i,xLabel:c,yLabel:u,showAxes:h=!0,formatY:l=ub,formatX:d=ub}){const f=P.useMemo(()=>{const g=OC(e,r),m=Math.max(r*6,240),v=10,S=8,C=[...e].sort((_,j)=>_.x-j.x).map(_=>{const j=g.maxX===g.minX?m/2:v+(_.x-g.minX)/(g.maxX-g.minX)*(m-v*2),A=g.maxY===g.minY?s/2:S+(g.maxY-_.y)/(g.maxY-g.minY)*(s-S*2);return{..._,cx:j,cy:A,leftPercent:j/m*100,topPercent:A/s*100}}),y=C.map((_,j)=>`${j===0?"M":"L"} ${_.cx.toFixed(1)} ${_.cy.toFixed(1)}`).join(" "),x=[g.maxY,(g.maxY+g.minY)/2,g.minY].map(_=>({value:_,y:g.maxY===g.minY?s/2:S+(g.maxY-_)/(g.maxY-g.minY)*(s-S*2)}));return{...g,chartWidth:m,points:C,path:y,gridLines:x}},[e,s,r]);return e.length===0?o.jsxs("div",{className:"font-mono text-text-muted text-xs",children:[i&&o.jsx("div",{className:"mb-1",children:i}),o.jsx("div",{children:"No data"})]}):o.jsxs("div",{className:"font-mono text-xs",children:[i&&o.jsx("div",{className:"text-text-secondary mb-2",children:i}),o.jsxs("div",{className:"flex gap-3",children:[h&&o.jsx("div",{className:"w-12 h-[78px] flex flex-col justify-between text-right text-text-muted",children:f.gridLines.map(g=>o.jsx("span",{children:l(g.value)},`${g.value}-${g.y}`))}),o.jsx("div",{className:"flex-1 min-w-0",children:o.jsxs("div",{className:"relative h-[78px]",children:[o.jsxs("svg",{viewBox:`0 0 ${f.chartWidth} ${s}`,className:"w-full h-[78px] overflow-visible",preserveAspectRatio:"none","aria-hidden":"true",children:[f.gridLines.map(g=>o.jsx("line",{x1:"0",x2:f.chartWidth,y1:g.y,y2:g.y,stroke:"currentColor",strokeDasharray:"3 4",className:"text-border/60"},`grid-${g.y}`)),f.points.map(g=>o.jsx("line",{x1:g.cx,x2:g.cx,y1:s-4,y2:g.cy,stroke:"currentColor",className:"text-border/40"},`guide-${g.cx}-${g.cy}`)),f.points.length>1&&o.jsx("path",{d:f.path,fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:"text-accent-primary/45"})]}),f.points.map(g=>o.jsx("div",{className:"absolute -translate-x-1/2 -translate-y-1/2",style:{left:`${g.leftPercent}%`,top:`${g.topPercent}%`},title:`${d(g.x)} -> ${l(g.y)}`,children:o.jsx("div",{className:"w-2.5 h-2.5 rounded-full bg-accent-primary/20 flex items-center justify-center",children:o.jsx("div",{className:"w-1.5 h-1.5 rounded-full bg-accent-primary"})})},`point-${g.x}-${g.y}`))]})})]}),h&&o.jsxs("div",{className:"flex items-start gap-3 text-text-muted mt-1",children:[o.jsx("span",{className:"w-12"}),o.jsxs("span",{className:"flex-1 flex justify-between",children:[o.jsx("span",{children:d(f.minX)}),o.jsx("span",{children:c}),o.jsx("span",{children:d(f.maxX)})]})]}),u&&h&&o.jsx("div",{className:"text-text-muted mt-1 text-center",children:u})]})}function MC({data:e,prefillLabel:r="Prefill Speed (tok/s) by Response",generationLabel:s="Generation Speed (tok/s) by Response",xLabel:i="response",width:c=60}){const u=e.map(l=>({x:l.x,y:l.ppSpeed})),h=e.map(l=>({x:l.x,y:l.tgSpeed}));return o.jsxs("div",{className:"space-y-5",children:[o.jsx(db,{data:u,width:c,label:r,xLabel:i}),o.jsx(db,{data:h,width:c,label:s,xLabel:i})]})}function IC(e){const r=new Map;for(const s of e.callDataPoints){const i=r.get(s.messageId)??[];r.set(s.messageId,[...i,s])}return e.dataPoints.map(s=>{const i=[...r.get(s.messageId)??[]].sort((c,u)=>c.callIndex-u.callIndex);return{...s,callCount:i.length,calls:i,isExpandable:i.length>1}})}function BC(e){return{mode:"responses",xLabel:"response",prefillLabel:"Prefill Speed (tok/s) by Response",generationLabel:"Generation Speed (tok/s) by Response",points:e.dataPoints.map(r=>({x:r.responseIndex,ppSpeed:r.prefillSpeed,tgSpeed:r.generationSpeed}))}}function zC(e){return{mode:"calls",xLabel:"context",prefillLabel:"Prefill Speed (tok/s) vs Context",generationLabel:"Generation Speed (tok/s) vs Context",points:e.callDataPoints.map(r=>({x:r.promptTokens,ppSpeed:r.prefillSpeed,tgSpeed:r.generationSpeed}))}}function PC(e){return e.callDataPoints.length>0?zC(e):BC(e)}function qd(e){if(e<60)return`${e.toFixed(1)}s`;const r=Math.floor(e/60),s=e%60;return`${r}m ${s.toFixed(0)}s`}function $s(e){return e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${(e/1e3).toFixed(1)}k`:e.toString()}function to(e){return e>=1e3?`${(e/1e3).toFixed(1)}k`:e.toFixed(1)}function HC(e){if(e.length===0)return"0 ctx";const r=Math.min(...e),s=Math.max(...e);return r===s?`${$s(r)} ctx`:`${$s(r)}-${$s(s)} ctx`}function Ql(e){return`${to(e)} t/s`}function ly(e){try{return new Date(e).toLocaleTimeString("en-US",{hour12:!1})}catch{return e}}function FC(e){return{exportedAt:new Date().toISOString(),providerId:e.providerId,providerName:e.providerName,backend:e.backend,model:e.model,label:e.label,summary:{totalTime:e.totalTime,aiTime:e.aiTime,toolTime:e.toolTime,prefillTokens:e.prefillTokens,generationTokens:e.generationTokens,avgPrefillSpeed:e.avgPrefillSpeed,avgGenerationSpeed:e.avgGenerationSpeed,responseCount:e.responseCount,llmCallCount:e.llmCallCount},responses:e.dataPoints.map(r=>({responseIndex:r.responseIndex,timestamp:r.timestamp,mode:r.mode,prefillTokens:r.prefillTokens,generationTokens:r.generationTokens,prefillSpeed:r.prefillSpeed,generationSpeed:r.generationSpeed,totalTime:r.totalTime,aiTime:r.aiTime,toolTime:r.toolTime})),llmCalls:e.callDataPoints.map(r=>({sessionCallIndex:r.sessionCallIndex,responseIndex:r.responseIndex,callIndex:r.callIndex,timestamp:r.timestamp,mode:r.mode,promptTokens:r.promptTokens,completionTokens:r.completionTokens,ttft:r.ttft,completionTime:r.completionTime,prefillSpeed:r.prefillSpeed,generationSpeed:r.generationSpeed,totalTime:r.totalTime}))}}function UC({isOpen:e,onClose:r,stats:s}){const i=P.useRef(null),[c,u]=P.useState({}),[h,l]=P.useState(()=>{var k;return((k=s.modelGroups[0])==null?void 0:k.key)??""});P.useEffect(()=>{var k;s.modelGroups.some(C=>C.key===h)||l(((k=s.modelGroups[0])==null?void 0:k.key)??"")},[h,s.modelGroups]);const d=P.useMemo(()=>s.modelGroups.find(k=>k.key===h)??s.modelGroups[0],[h,s.modelGroups]),f=P.useMemo(()=>d?IC(d):[],[d]),g=P.useMemo(()=>d?PC(d):{mode:"responses",xLabel:"response",prefillLabel:"",generationLabel:"",points:[]},[d]),m=P.useCallback(k=>{u(C=>({...C,[k]:!C[k]}))},[]),v=P.useCallback(()=>{if(!d)return;const k=FC(d);navigator.clipboard.writeText(JSON.stringify(k,null,2)).catch(C=>console.error("Failed to copy:",C))},[d]),S=P.useCallback(async()=>{if(i.current)try{const k=(await fh(async()=>{const{default:b}=await import("./html2canvas.esm-QH1iLAAe.js");return{default:b}},[])).default,C=await k(i.current,{backgroundColor:"#1a1a1a",scale:2}),y=document.createElement("a");y.download=`openfox-stats-${new Date().toISOString().slice(0,10)}.png`,y.href=C.toDataURL("image/png"),y.click()}catch(k){console.error("Failed to export PNG:",k),v()}},[v]);return o.jsx(At,{isOpen:e,onClose:r,title:"Session Stats",size:"lg",children:o.jsxs("div",{ref:i,className:"space-y-6",children:[o.jsx("section",{children:o.jsx("div",{className:"flex flex-wrap gap-2",children:s.modelGroups.map(k=>o.jsx("button",{onClick:()=>l(k.key),className:`px-3 py-1.5 rounded border text-xs transition-colors ${k.key===(d==null?void 0:d.key)?"border-accent-primary bg-accent-primary/10 text-accent-primary":"border-border text-text-muted hover:text-text-primary hover:bg-bg-tertiary/40"}`,title:k.label,children:k.label},k.key))})}),d&&o.jsxs("section",{children:[o.jsx("h3",{className:"text-sm font-semibold text-text-secondary mb-3 uppercase tracking-wide",children:"Summary"}),o.jsxs("div",{className:"grid grid-cols-2 md:grid-cols-5 gap-4",children:[o.jsx(Hr,{label:"AI Time",value:qd(d.aiTime)}),o.jsx(Hr,{label:"Total Time",value:qd(d.totalTime)}),o.jsx(Hr,{label:"Tool Time",value:qd(d.toolTime)}),o.jsx(Hr,{label:"Responses",value:d.responseCount.toString()}),o.jsx(Hr,{label:"LLM Calls",value:d.llmCallCount.toString()})]}),o.jsxs("div",{className:"grid grid-cols-2 md:grid-cols-4 gap-4 mt-3",children:[o.jsx(Hr,{label:"Prefill Tokens",value:$s(d.prefillTokens),subValue:`@ ${to(d.avgPrefillSpeed)} tok/s`}),o.jsx(Hr,{label:"Gen Tokens",value:$s(d.generationTokens),subValue:`@ ${to(d.avgGenerationSpeed)} tok/s`}),o.jsx(Hr,{label:"Avg PP Speed",value:`${to(d.avgPrefillSpeed)}`,subValue:"tok/s"}),o.jsx(Hr,{label:"Avg TG Speed",value:`${to(d.avgGenerationSpeed)}`,subValue:"tok/s"})]})]}),d&&g.points.length>1&&o.jsxs("section",{children:[o.jsxs("div",{className:"flex items-center justify-between mb-3",children:[o.jsx("h3",{className:"text-sm font-semibold text-text-secondary uppercase tracking-wide",children:"Performance Progression"}),o.jsxs("div",{className:"flex items-center gap-2",children:[o.jsx("button",{onClick:v,className:"px-2 py-1 text-xs text-text-muted hover:text-text-primary hover:bg-bg-tertiary rounded transition-colors",children:"Copy JSON"}),o.jsx("button",{onClick:S,className:"px-2 py-1 text-xs text-text-muted hover:text-text-primary hover:bg-bg-tertiary rounded transition-colors",children:"Save PNG"})]})]}),o.jsx("div",{className:"bg-bg-tertiary/50 rounded p-4",children:o.jsx(MC,{data:g.points,width:50,prefillLabel:g.prefillLabel,generationLabel:g.generationLabel,xLabel:g.xLabel})})]}),d&&o.jsxs("section",{children:[o.jsxs("h3",{className:"text-sm font-semibold text-text-secondary mb-3 uppercase tracking-wide",children:["Response Log (",d.responseCount," responses)"]}),o.jsx("div",{className:"overflow-y-auto bg-bg-tertiary/30 rounded",children:o.jsxs("table",{className:"w-full table-fixed border-separate border-spacing-0 text-xs",children:[o.jsxs("colgroup",{children:[o.jsx("col",{className:"w-[7%]"}),o.jsx("col",{className:"w-[14%]"}),o.jsx("col",{className:"w-[10%]"}),o.jsx("col",{className:"w-[14%]"}),o.jsx("col",{className:"w-[14%]"}),o.jsx("col",{className:"w-[14%]"}),o.jsx("col",{className:"w-[11%]"}),o.jsx("col",{className:"w-[2%]"})]}),o.jsx("thead",{children:o.jsxs("tr",{className:"text-[10px] uppercase tracking-wide text-text-muted/80",children:[o.jsx("th",{className:"px-3 py-2 text-center font-medium",children:"#"}),o.jsx("th",{className:"px-2 py-2 text-center font-medium",children:"At"}),o.jsx("th",{className:"px-2 py-2 text-center font-medium",children:"Time"}),o.jsx("th",{className:"px-2 py-2 text-center font-medium",children:"Context"}),o.jsx("th",{className:"px-2 py-2 text-center font-medium",children:"PP t/s"}),o.jsx("th",{className:"px-2 py-2 text-center font-medium",children:"TG t/s"}),o.jsx("th",{className:"px-2 py-2 text-center font-medium",children:"Calls"}),o.jsx("th",{className:"px-2 py-2"})]})}),o.jsx("tbody",{children:f.map((k,C)=>o.jsxs(P.Fragment,{children:[o.jsx($C,{row:k,index:C,isExpanded:c[k.messageId]??!1,onToggle:k.isExpandable?()=>m(k.messageId):void 0}),(c[k.messageId]??!1)&&k.calls.map((y,b)=>o.jsx(qC,{dataPoint:y,index:b},`${y.messageId}-${y.callIndex}`))]},k.messageId))})]})})]})]})})}function Hr({label:e,value:r,subValue:s}){return o.jsxs("div",{className:"bg-bg-tertiary/50 rounded p-3",children:[o.jsx("div",{className:"text-text-muted text-xs mb-1",children:e}),o.jsx("div",{className:"text-text-primary text-lg font-semibold",children:r}),s&&o.jsx("div",{className:"text-text-muted text-xs",children:s})]})}function $C({row:e,index:r,isExpanded:s,onToggle:i}){const c=e.calls.length>0?HC(e.calls.map(u=>u.promptTokens)):`${$s(e.prefillTokens)} ctx`;return o.jsxs("tr",{onClick:i,className:`${r%2===0?"bg-bg-tertiary/20":""} ${i?"cursor-pointer hover:bg-bg-tertiary/35 transition-colors":""}`,children:[o.jsx("td",{className:"px-3 py-2 text-center text-text-muted align-middle",children:e.responseIndex}),o.jsx("td",{className:"px-2 py-2 text-center text-text-muted font-mono align-middle whitespace-nowrap",children:ly(e.timestamp)}),o.jsxs("td",{className:"px-2 py-2 text-center text-text-muted align-middle whitespace-nowrap",children:[e.totalTime.toFixed(1),"s"]}),o.jsx("td",{className:"px-2 py-2 text-center text-text-primary font-mono align-middle whitespace-nowrap",children:c.replace(/ ctx$/,"")}),o.jsx("td",{className:"px-2 py-2 text-center text-text-primary font-mono align-middle whitespace-nowrap",children:Ql(e.prefillSpeed)}),o.jsx("td",{className:"px-2 py-2 text-center text-text-primary font-mono align-middle whitespace-nowrap",children:Ql(e.generationSpeed)}),o.jsx("td",{className:"px-2 py-2 text-center text-text-muted font-mono align-middle whitespace-nowrap",children:e.callCount}),o.jsx("td",{className:"px-2 py-2 text-center text-text-muted align-middle whitespace-nowrap",children:e.isExpandable?s?"v":">":""})]})}function qC({dataPoint:e,index:r}){const s=e.temperature!==void 0||e.topP!==void 0||e.topK!==void 0||e.maxTokens!==void 0;return o.jsxs(o.Fragment,{children:[o.jsxs("tr",{className:`${r%2===0?"bg-bg-tertiary/10":"bg-bg-tertiary/5"}`,children:[o.jsxs("td",{className:"px-3 py-2 pl-6 text-center text-text-muted align-middle border-l border-border/60",children:["c",e.callIndex]}),o.jsx("td",{className:"px-2 py-2 text-center text-text-muted font-mono align-middle whitespace-nowrap",children:ly(e.timestamp)}),o.jsxs("td",{className:"px-2 py-2 text-center text-text-muted align-middle whitespace-nowrap",children:[e.totalTime.toFixed(1),"s"]}),o.jsx("td",{className:"px-2 py-2 text-center text-text-primary font-mono align-middle whitespace-nowrap",children:$s(e.promptTokens)}),o.jsx("td",{className:"px-2 py-2 text-center text-text-primary font-mono align-middle whitespace-nowrap",children:Ql(e.prefillSpeed)}),o.jsx("td",{className:"px-2 py-2 text-center text-text-primary font-mono align-middle whitespace-nowrap",children:Ql(e.generationSpeed)}),o.jsx("td",{className:"px-2 py-2 text-center text-text-muted font-mono align-middle whitespace-nowrap",children:e.callIndex}),o.jsx("td",{className:"px-2 py-2"})]}),s&&o.jsx("tr",{className:`${r%2===0?"bg-bg-tertiary/5":"bg-bg-tertiary/[2.5%]"}`,children:o.jsx("td",{colSpan:8,className:"px-6 py-1.5 border-l border-border/60",children:o.jsxs("div",{className:"flex flex-wrap gap-x-4 gap-y-1 text-[10px] text-text-muted",children:[e.temperature!==void 0&&o.jsxs("span",{children:["temp: ",e.temperature.toFixed(2)]}),e.topP!==void 0&&o.jsxs("span",{children:["topP: ",e.topP.toFixed(2)]}),e.topK!==void 0&&o.jsxs("span",{children:["topK: ",e.topK]}),e.maxTokens!==void 0&&o.jsxs("span",{children:["maxTok: ",e.maxTokens]})]})})})]})}const WC={pending:{icon:"○",color:"text-text-muted",label:"Pending"},in_progress:{icon:"●",color:"text-accent-warning",label:"In Progress",animate:!0},completed:{icon:"◉",color:"text-purple-400",label:"Completed"},passed:{icon:"✓",color:"text-accent-success",label:"Passed"},failed:{icon:"✗",color:"text-accent-error",label:"Failed"}},VC=P.memo(function({criteria:r}){if(r.length===0)return o.jsx("div",{className:"text-text-muted text-sm text-center py-2",children:"No criteria yet"});const s={pending:0,in_progress:0,completed:0,passed:0,failed:0};for(const c of r){const u=c.status.type;u in s&&s[u]++}const i=Object.keys(s).filter(c=>s[c]>0);return o.jsxs("div",{className:"space-y-1",children:[o.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[o.jsx("span",{className:"font-semibold text-text-primary",children:"Total:"}),o.jsx("span",{className:"text-text-secondary",children:r.length})]}),o.jsx("div",{className:"space-y-1",children:i.map(c=>{const u=WC[c];return o.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[o.jsx("span",{className:`${u.color} ${u.animate?"animate-pulse":""} text-sm leading-tight`,children:u.icon}),o.jsxs("span",{className:"text-text-muted",children:[u.label,":"]}),o.jsx("span",{className:"text-text-primary font-medium",children:s[c]})]},c)})})]})});function GC({isOpen:e,onClose:r}){const s=gr(C=>C.config),i=gr(C=>C.saveConfig),[c,u]=P.useState(""),[h,l]=P.useState(""),[d,f]=P.useState(!1),[g,m]=P.useState(!1),[v,S]=P.useState(!1);P.useEffect(()=>{e&&(u((s==null?void 0:s.command)??""),l((s==null?void 0:s.url)??""),f((s==null?void 0:s.hotReload)??!1),m((s==null?void 0:s.disableInspect)??!1))},[e,s]);const k=async()=>{!c.trim()||!h.trim()||(S(!0),await i({command:c.trim(),url:h.trim(),hotReload:d,disableInspect:g}),S(!1),r())};return o.jsx(At,{isOpen:e,onClose:r,title:"Dev Server Config",size:"sm",children:o.jsxs("div",{className:"space-y-4",children:[o.jsxs("div",{children:[o.jsx("label",{className:"block text-xs text-text-secondary mb-1",children:"Command"}),o.jsx("input",{className:"input w-full",type:"text",value:c,onChange:C=>u(C.target.value),placeholder:"npm run dev"})]}),o.jsxs("div",{children:[o.jsx("label",{className:"block text-xs text-text-secondary mb-1",children:"Dev URL"}),o.jsx("input",{className:"input w-full",type:"text",value:h,onChange:C=>l(C.target.value),placeholder:"http://localhost:3000"})]}),o.jsxs("div",{className:"flex items-center gap-2",children:[o.jsx("input",{type:"checkbox",id:"hotReload",checked:d,onChange:C=>f(C.target.checked),className:"rounded border-border bg-bg-tertiary"}),o.jsx("label",{htmlFor:"hotReload",className:"text-xs text-text-secondary",children:"Hot Reload"})]}),o.jsxs("div",{className:"flex items-center gap-2",children:[o.jsx("input",{type:"checkbox",id:"disableInspect",checked:g,onChange:C=>m(C.target.checked),className:"rounded border-border bg-bg-tertiary"}),o.jsx("label",{htmlFor:"disableInspect",className:"text-xs text-text-secondary",children:"Disable inspect feedback"})]}),o.jsxs("div",{className:"flex justify-end gap-2 pt-2",children:[o.jsx("button",{className:"btn btn-secondary",onClick:r,children:"Cancel"}),o.jsx("button",{className:"btn btn-primary",onClick:k,disabled:v||!c.trim()||!h.trim(),children:v?"Saving...":"Save"})]})]})})}const hb={30:"text-black",31:"text-red-400",32:"text-accent-success",33:"text-accent-warning",34:"text-blue-400",35:"text-purple-400",36:"text-cyan-400",37:"text-gray-300",90:"text-gray-500",91:"text-red-500",92:"text-green-500",93:"text-yellow-400",94:"text-blue-500",95:"text-pink-400",96:"text-cyan-500",97:"text-white"},KC={40:"bg-black",41:"bg-red-900",42:"bg-green-900",43:"bg-yellow-900",44:"bg-blue-900",45:"bg-purple-900",46:"bg-cyan-900",47:"bg-gray-700"},fb={1:"font-bold",2:"opacity-75",4:"underline",7:"bg-bg-secondary"},YC="text-text-primary";function XC(e){const r=[],s=/\x1b\[([0-9;]+)m/g;let i=0,c="text-text-primary",u;try{for(;(u=s.exec(e))!==null;){if(u.index>i){const f=e.slice(i,u.index);f&&r.push({text:f,className:c})}const h=u[1];if(!h)continue;const l=h.split(";").map(Number);if(l.length===0||l[0]===0){c="text-text-primary";continue}const d=[];for(const f of l)if(f>=30&&f<=37){const g=hb[f];g&&d.push(g)}else if(f>=40&&f<=47){const g=KC[f];g&&d.push(g)}else if(f>=90&&f<=97){const g=hb[f];g&&d.push(g)}else if(f in fb){const g=fb[f];g&&d.push(g)}else f===39?d.push(YC):f===49&&(c=c.split(" ").filter(g=>!g.startsWith("bg-")).join(" "));d.length>0&&(c=d.join(" ")),i=s.lastIndex}if(i<e.length){const h=e.slice(i);h&&r.push({text:h,className:c})}return r}catch(h){return console.warn("ANSI parsing failed, stripping codes:",h),[{text:ZC(e),className:"text-text-primary"}]}}function ZC(e){return e.replace(/\x1b\[([0-9;]+)m/g,"")}function co(e){const r=XC(e),s=[];return r.forEach((i,c)=>{const u=i.text.split(`
84
+ `,children:[o.jsxs("div",{className:"p-4 border-b border-border flex gap-2",children:[o.jsx(Fn,{href:`/p/${e}/new`,className:"flex-1 block text-center rounded font-medium transition-colors bg-accent-primary/25 text-text-primary hover:bg-accent-primary/40 px-3 py-1.5 text-sm","data-testid":"sidebar-new-session-button",children:"+ New Session"}),o.jsx(bo,{items:[{label:"Edit project settings",onClick:()=>u(!0)},{label:"Delete all sessions",onClick:_,danger:!0}],trigger:o.jsx("button",{className:"flex-shrink-0 p-2.5 rounded hover:bg-bg-tertiary text-text-muted hover:text-text-primary transition-colors",title:"Options",children:o.jsx(Bh,{})})}),s&&o.jsx(lo,{onClick:s,className:"md:hidden",variant:"sidebar",size:"md"})]}),k&&o.jsx(hC,{isOpen:c,onClose:()=>u(!1),project:k}),o.jsx("div",{className:"flex-1 overflow-y-auto",children:b.length===0?o.jsx("div",{className:"p-4 text-center text-text-muted text-xs",children:"No sessions"}):o.jsxs(o.Fragment,{children:[o.jsx("div",{className:"divide-y divide-border",children:mC(b,l,d,x,e)}),S&&o.jsx("div",{className:"p-4 text-center text-text-muted text-xs",children:"Loading more..."}),o.jsx("div",{ref:C,className:"h-px"})]})})]})]})}function mC(e,r,s,i,c){const u=iy(e);return Array.from(u).map(([h,l])=>{const d=l[0];return d?o.jsxs("div",{children:[o.jsx("div",{className:"px-4 py-2 bg-bg-tertiary/30 text-text-muted text-xs font-medium",children:ry(d.updatedAt)}),l.map(f=>{const g=(r==null?void 0:r.id)===f.id,m=s.includes(f.id),v=f.isRunning;return o.jsx("div",{className:`w-full px-4 py-3 text-left hover:bg-bg-tertiary/50 transition-colors group ${g?"bg-bg-tertiary":""}`,children:o.jsxs(Fn,{href:`/p/${c}/s/${f.id}`,className:`block ${g?"text-accent-primary":"text-text-primary"} hover:text-accent-primary`,children:[o.jsxs("div",{className:"flex justify-between items-center mb-1",children:[o.jsx("span",{className:`font-medium truncate text-sm ${g?"text-accent-primary":"text-text-primary"}`,children:f.title??f.id.slice(0,6)}),o.jsx(bo,{items:[{label:"Delete session",onClick:S=>i(f.id,S),danger:!0}],trigger:o.jsx("button",{onClick:S=>S.preventDefault(),className:"p-1.5 rounded hover:bg-bg-tertiary text-text-muted hover:text-text-primary transition-all",title:"Options",children:o.jsx(Bh,{})})})]}),o.jsxs("div",{className:"flex items-center gap-2 mt-1",children:[v?o.jsx(Nw,{}):m&&!g?o.jsx("span",{"aria-label":"Unread activity",title:"Unread activity",className:"w-2 h-2 rounded-full bg-amber-400 flex-shrink-0"}):null,o.jsx("span",{className:"text-text-muted text-xs flex-shrink-0",children:uc(f.updatedAt)}),o.jsxs("span",{className:"text-text-muted text-xs flex-shrink-0",children:[f.messageCount," messages"]})]})]})},f.id)})]},h):null})}const ab=["⠋","⠙","⠹","⠸","⠼","⠴"];function gC(){var l;const e=Ft(d=>d.currentProject),r=Ce(d=>d.currentSession),s=qv(),i=!1,c=P.useRef(0),u=P.useRef(null);P.useEffect(()=>(s?(u.current=window.setInterval(()=>{c.current=(c.current+1)%ab.length,h()},150),h()):(u.current&&(clearInterval(u.current),u.current=null),h()),()=>{u.current&&(clearInterval(u.current),u.current=null)}),[s,e,r,i]);const h=()=>{var m;const f=(m=r==null?void 0:r.metadata)==null?void 0:m.title,g=s?`${ab[c.current]} `:"";e&&f?document.title=`${g}${e.name} - ${f} | OpenFox`:e?document.title=`${g}${e.name} | OpenFox`:document.title=`${g}OpenFox`};return typeof window<"u"&&((l=r==null?void 0:r.metadata)!=null&&l.title)&&window.document.documentElement.setAttribute("data-session-title",r.metadata.title),null}function xC({isOpen:e,onClose:r,projectName:s,onConfirm:i}){const c=()=>{i(),r()};return o.jsx(At,{isOpen:e,onClose:r,title:"Delete Project",size:"sm",children:o.jsxs("div",{className:"space-y-4",children:[o.jsxs("p",{className:"text-text-secondary",children:["This will permanently delete the project ",o.jsx("span",{className:"font-semibold text-text-primary",children:s})," and all its sessions from OpenFox. The project files on disk will remain untouched."]}),o.jsxs("div",{className:"flex justify-end gap-2",children:[o.jsx(nt,{variant:"secondary",onClick:r,children:"Cancel"}),o.jsx(nt,{variant:"danger",onClick:c,children:"Delete"})]})]})})}const dc=P.forwardRef(({className:e="",...r},s)=>o.jsx("input",{ref:s,className:`bg-bg-tertiary border border-border rounded px-3 py-2 text-text-primary placeholder-text-muted focus:outline-none focus:ring-2 focus:ring-accent-primary/50 focus:border-accent-primary ${e}`,...r}));dc.displayName="Input";function bC(e){return!e||e.trim()===""?{valid:!1,error:"Project name cannot be empty"}:/^[a-zA-Z0-9._-]+$/.test(e)?{valid:!0}:{valid:!1,error:"Project name can only contain letters, numbers, hyphens, underscores, and dots"}}function vC({isOpen:e,onClose:r}){const[,s]=lr(),[i,c]=P.useState(""),[u,h]=P.useState(null),[l,d]=P.useState(!1),[f,g]=P.useState(""),m=P.useRef(null);P.useEffect(()=>{e&&(ke("/api/config").then(C=>C.json()).then(C=>{C.workdir&&g(C.workdir)}),c(""),h(null),d(!1),setTimeout(()=>{var C;(C=m.current)==null||C.focus()},100))},[e]);const v=P.useCallback(async C=>{C.preventDefault();const y=bC(i);if(!y.valid){h(y.error);return}d(!0),h(null);const b=`${f}/${i}`;try{const x=await ke("/api/projects",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:i,workdir:b})});if(!x.ok){const A=await x.json().catch(()=>({}));throw new Error(A.error||"Failed to create project")}const j=(await x.json()).project;r(),s(`/p/${j.id}`)}catch(x){h(x instanceof Error?x.message:"Failed to create project"),d(!1)}},[i,s,r,f]),S=P.useCallback(()=>{c(""),h(null),r()},[r]),k=i?`${f}/${i}`:"";return o.jsx(At,{isOpen:e,onClose:S,title:"Create New Project",size:"sm",children:o.jsxs("form",{onSubmit:v,className:"space-y-4",children:[o.jsxs("div",{children:[o.jsx("label",{htmlFor:"project-name",className:"block text-sm font-medium text-text-secondary mb-2",children:"Project Name"}),o.jsx(dc,{ref:m,id:"project-name",value:i,onChange:C=>{c(C.target.value),h(null)},placeholder:"my-project",disabled:l,"data-testid":"create-project-name-input",className:"w-full"}),i&&o.jsxs("div",{className:"mt-2 text-xs text-text-muted",children:["Full path: ",o.jsx("span",{className:"font-mono",children:k})]}),u&&o.jsx("div",{className:"mt-3 p-3 bg-accent-error/10 border border-accent-error/30 rounded text-sm text-accent-error",children:u})]}),o.jsxs("div",{className:"flex justify-end gap-2",children:[o.jsx(nt,{type:"button",variant:"secondary",onClick:S,disabled:l,children:"Cancel"}),o.jsx(nt,{type:"submit",variant:"primary",disabled:l||!i.trim(),"data-testid":"create-project-submit-button",className:"min-w-[100px]",children:l?o.jsxs("span",{className:"flex items-center gap-2",children:[o.jsx(qi,{className:"h-4 w-4"}),"Creating..."]}):"Create"})]})]})})}const yC={sm:"w-4 h-4",md:"w-8 h-8",lg:"w-12 h-12"};function vo({size:e="md",className:r=""}){return o.jsx("div",{className:`animate-spin border-2 border-accent-primary border-t-transparent rounded-full ${yC[e]} ${r}`})}function _C({text:e,...r}){return o.jsxs("div",{className:"text-center",children:[o.jsx(vo,{...r,className:"mx-auto mb-4"}),e&&o.jsx("div",{className:"text-text-secondary",children:e})]})}function oy({onSelect:e,onClose:r,initialPath:s}){const[i,c]=P.useState(null),[u,h]=P.useState(!0),[l,d]=P.useState(""),[f,g]=P.useState(-1),m=P.useRef(null),v=P.useRef([]),S=P.useCallback(async x=>{h(!0),d(""),g(-1);try{const _=x?`/api/directories?path=${encodeURIComponent(x)}`:"/api/directories",A=await(await ke(_)).json();c(A)}catch(_){console.error("Failed to load directories:",_)}finally{h(!1)}},[]);P.useEffect(()=>{S(s)},[s,S]);const k=((i==null?void 0:i.current)??"").split("/").filter(Boolean).map((x,_,j)=>({name:x,path:"/"+j.slice(0,_+1).join("/")})),C=(i==null?void 0:i.directories.filter(x=>l===""||x.name.toLowerCase().includes(l.toLowerCase())))??[],y=[...i!=null&&i.parent?[{type:"parent",path:i.parent,name:".."}]:[],...C.map(x=>({type:"dir",path:x.path,name:x.name}))];P.useEffect(()=>{g(l?0:-1)},[l,C.length]),P.useEffect(()=>{var x;f>=0&&v.current[f]&&((x=v.current[f])==null||x.scrollIntoView({block:"nearest"}))},[f]);const b=x=>{var _;if(x.key==="ArrowDown")x.preventDefault(),g(j=>Math.min(j+1,y.length-1));else if(x.key==="ArrowUp")x.preventDefault(),g(j=>Math.max(j-1,0));else if(x.key==="Enter"){if(x.preventDefault(),f>=0&&y[f]){const j=y[f];j.type,S(j.path)}}else x.key==="Escape"&&(d(""),(_=m.current)==null||_.focus())};return o.jsxs(At,{isOpen:!0,onClose:r,title:"Select Folder",size:"lg",children:[i&&o.jsx("div",{className:"px-3 py-2 bg-bg-tertiary/30 -mx-4 -mt-4 mb-4 border-b border-border",children:o.jsxs("div",{className:"flex items-center text-xs overflow-x-auto",children:[k.map((x,_)=>o.jsxs("span",{className:"flex items-center shrink-0",children:[o.jsx("span",{className:"text-text-muted",children:"/"}),o.jsx("button",{onClick:()=>S(x.path),className:`px-1 ${_===k.length-1?"text-accent-primary font-medium":"text-text-secondary hover:text-accent-primary"}`,children:x.name})]},x.path)),k.length===0&&o.jsx("button",{onClick:()=>S("/"),className:"text-text-muted hover:text-accent-primary",children:"/"})]})}),o.jsx("div",{className:"px-4 mb-3",children:o.jsxs("div",{className:"relative",children:[o.jsx("span",{className:"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-text-muted pointer-events-none flex items-center justify-center",children:o.jsx(Hh,{})}),o.jsx(dc,{autoFocus:!0,ref:m,value:l,onChange:x=>d(x.target.value),onKeyDown:b,placeholder:"Filter directories...",className:"w-full pl-9"})]})}),o.jsx("div",{className:"flex-1 overflow-y-auto -mx-4",children:u?o.jsx("div",{className:"p-8 text-center",children:o.jsx(vo,{size:"sm"})}):y.length===0?o.jsx("div",{className:"p-8 text-center text-text-muted text-sm",children:l?"No matching directories":"No subdirectories"}):o.jsx("div",{className:"divide-y divide-border",children:y.map((x,_)=>o.jsxs("button",{ref:j=>{v.current[_]=j},onClick:()=>S(x.path),onDoubleClick:()=>e(x.path),className:`w-full p-3 flex items-center gap-3 text-left transition-colors ${_===f?"bg-accent-primary/20 text-accent-primary":"hover:bg-bg-tertiary/50"}`,children:[x.type==="parent"?o.jsx(hw,{className:"w-5 h-5 text-text-muted"}):o.jsx(zh,{className:"w-5 h-5"}),o.jsx("span",{className:"flex-1",children:x.name}),_===f&&o.jsx("span",{className:"text-xs text-text-muted",children:"⏎ navigate · dbl-click select"})]},x.path))})}),o.jsxs("div",{className:"flex flex-col gap-2 pt-4 border-t border-border mt-4 -mx-4 -mb-4 p-4",children:[(i==null?void 0:i.current)&&o.jsx("button",{onClick:()=>e(i.current),className:"w-full px-4 py-2 bg-accent-primary text-text-primary rounded-lg font-medium hover:bg-accent-primary/90 transition-colors",children:"Select this folder"}),o.jsx("button",{onClick:r,className:"w-full text-center text-text-muted hover:text-text-secondary text-sm",children:"Cancel"})]})]})}function SC({isOpen:e,onClose:r}){const[,s]=lr(),[i,c]=P.useState(!1),[u,h]=P.useState(null),[l,d]=P.useState(!1),f=Ft(N=>N.projects),g=Ft(N=>N.createProject),m=Ft(N=>N.listProjects),v=Ft(N=>N.deleteProject),[S,k]=P.useState(null),[C,y]=P.useState(null),b=(N,D=32)=>{if(N.length<=D)return N;const T=N.split("/").filter(Boolean);if(T.length<=2)return N;const z=T[0],O=T[T.length-1],q=T.slice(1,-1).join("/"),V=D-z.length-O.length-3;if(V<0)return N;const W=q.slice(0,Math.floor(V/2)),I=q.slice(-Math.ceil(V/2));return`/${z}/${W}...${I}/${O}`};P.useEffect(()=>{ke("/api/config").then(N=>N.json()).then(N=>{N.workdir&&h(N.workdir)})},[]),P.useEffect(()=>{e&&m()},[e,m]);const x=N=>{s(`/p/${N}`),r()},_=(N,D)=>{D.stopPropagation(),k(N)},j=()=>{S&&(v(S.id),k(null))},A=N=>{const D=N.split("/").filter(Boolean).pop()??"";g(D,N),m(),y(N)};return P.useEffect(()=>{if(C){const N=f.find(D=>D.workdir===C);N&&(s(`/p/${N.id}`),r(),y(null))}},[f,C,s,r]),e?o.jsxs(At,{isOpen:e,onClose:r,title:"Open Project",size:"xl",footer:o.jsx("div",{className:"flex justify-end gap-2",children:o.jsx(nt,{variant:"secondary",onClick:r,children:"Close"})}),children:[o.jsxs("div",{className:"flex flex-col sm:flex-row flex-1 -m-4",children:[o.jsxs("div",{className:"w-full sm:w-1/2 border-b sm:border-b-0 sm:border-r border-border flex flex-col max-h-[40vh] sm:max-h-[50vh]",children:[o.jsx("div",{className:"p-3 border-b border-border bg-bg-tertiary/30 shrink-0",children:o.jsx("h3",{className:"font-medium text-sm text-text-secondary",children:"Recent Projects"})}),o.jsx("div",{className:"flex-1 overflow-y-auto",children:f.length===0?o.jsxs("div",{className:"p-6 text-center text-text-muted text-sm",children:[o.jsx("p",{className:"mb-2",children:"No recent projects"}),o.jsx("p",{className:"text-xs",children:'Click "Create new project" to add one'})]}):o.jsx("div",{className:"divide-y divide-border",children:f.map(N=>o.jsxs("div",{className:"group flex items-center gap-3 p-3 hover:bg-bg-tertiary/50 transition-colors",children:[o.jsxs("button",{onClick:()=>x(N.id),className:"flex-1 flex items-center gap-3 text-left",children:[o.jsx(zh,{className:"w-5 h-5 text-accent-primary"}),o.jsxs("div",{className:"flex-1 min-w-0",children:[o.jsx("div",{className:"font-medium truncate",children:N.name}),o.jsx("div",{className:"text-xs text-text-muted truncate",children:b(N.workdir)})]})]}),o.jsx("button",{onClick:D=>_(N,D),className:"text-accent-error/70 hover:text-accent-error p-1",title:"Delete project",children:o.jsx(Ph,{className:"w-4 h-4"})})]},N.id))})})]}),o.jsx("div",{className:"w-full sm:w-1/2 flex flex-col items-center justify-center p-6 sm:p-8 text-center",children:o.jsxs("div",{className:"flex flex-col gap-3 w-full max-w-sm",children:[o.jsx(nt,{variant:"primary",onClick:()=>d(!0),children:"Select existing project"}),o.jsx(nt,{variant:"secondary",onClick:()=>c(!0),"data-testid":"open-project-create-button",children:"Create new project"})]})})]}),i&&o.jsx(vC,{isOpen:i,onClose:()=>c(!1)}),S&&o.jsx(xC,{isOpen:!0,onClose:()=>k(null),projectName:S.name,onConfirm:j}),l&&o.jsx(oy,{initialPath:u??void 0,onSelect:N=>{A(N),d(!1)},onClose:()=>d(!1)})]}):null}function wC(){const[e,r]=P.useState(!1),s=Ce(m=>m.sessions),i=Ft(m=>m.projects),c=Ft(m=>m.loading),u=Ft(m=>m.listProjects),h=Ce(m=>m.listSessions),l=Ce(m=>m.connectionStatus);P.useEffect(()=>{l==="connected"&&(u(),h())},[l,u,h]);const d=[...i].sort((m,v)=>{const S=s.filter(b=>b.workdir.startsWith(m.workdir)),k=s.filter(b=>b.workdir.startsWith(v.workdir)),C=S.length>0?new Date(S.reduce((b,x)=>new Date(x.updatedAt)>new Date(b.updatedAt)?x:b).updatedAt).getTime():new Date(m.updatedAt).getTime();return(k.length>0?new Date(k.reduce((b,x)=>new Date(x.updatedAt)>new Date(b.updatedAt)?x:b).updatedAt).getTime():new Date(v.updatedAt).getTime())-C}),f=m=>{const v=i.find(S=>S.id===m);return v?s.filter(S=>S.workdir.startsWith(v.workdir)).sort((S,k)=>new Date(k.updatedAt).getTime()-new Date(S.updatedAt).getTime()).slice(0,5):[]},g=()=>{r(!0)};return o.jsxs("div",{className:"flex-1 flex flex-col overflow-y-auto bg-primary",children:[o.jsxs("div",{className:"max-w-5xl mx-auto w-full p-4 md:p-8",children:[o.jsxs("div",{className:"mb-6 md:mb-8 flex items-center justify-between",children:[o.jsxs("div",{children:[o.jsx("h1",{className:"text-3xl font-bold text-accent-primary",children:"OpenFox"}),o.jsx("p",{className:"text-text-secondary",children:"Local LLM-powered coding assistant with contract-driven execution"})]}),o.jsx(nt,{variant:"primary",onClick:g,children:"Open Project"})]}),d.map(m=>{const v=f(m.id);return o.jsx("div",{className:"mb-6 md:mb-8",children:o.jsxs("div",{className:"bg-bg-secondary border border-border rounded-lg overflow-hidden",children:[o.jsxs("div",{className:"p-3 md:p-4 border-b border-border flex items-center justify-between gap-2",children:[o.jsxs(Fn,{href:`/p/${m.id}`,className:"flex items-center gap-2 cursor-pointer hover:opacity-80 transition-opacity flex-1",children:[o.jsx(zh,{className:"w-5 h-5 text-accent-primary flex-shrink-0"}),o.jsx("span",{className:"text-text-primary font-semibold",children:m.name})]}),o.jsx(Fn,{href:`/p/${m.id}/new`,className:"rounded font-medium transition-colors bg-accent-primary/25 text-text-primary hover:bg-accent-primary/40 px-1.5 py-1 text-xs",children:"+ New Session"})]}),o.jsx("div",{className:"divide-y divide-border",children:v.length>0?v.map(S=>{const k=i.find(y=>S.workdir.startsWith(y.workdir)),C=k?`/p/${k.id}/s/${S.id}`:"#";return o.jsx(Fn,{href:C,className:"block p-3 md:p-4 hover:bg-bg-tertiary/50 cursor-pointer transition-colors",children:o.jsxs("div",{className:"flex items-center justify-between gap-2",children:[o.jsx("div",{className:"flex items-center gap-3 flex-1 min-w-0",children:o.jsx("div",{className:"flex-1 min-w-0",children:o.jsx("div",{className:"text-sm text-text-muted truncate",children:S.title??S.id.slice(0,8)})})}),o.jsxs("div",{className:"flex items-center gap-2 flex-shrink-0",children:[o.jsx("span",{className:"text-text-muted text-xs",children:sC(S.updatedAt)}),o.jsxs("span",{className:"text-text-muted text-xs",children:[S.messageCount," msgs"]})]})]})},S.id)}):o.jsx("div",{className:"p-3 md:p-4 text-text-muted text-sm",children:"No sessions yet"})})]})},m.id)}),d.length===0&&!c&&o.jsx("div",{className:"text-center py-12 text-text-muted",children:"No projects yet. Open a project to get started."}),c&&o.jsx("div",{className:"flex justify-center py-12",children:o.jsx(vo,{})})]}),e&&o.jsx(SC,{isOpen:e,onClose:()=>r(!1)})]})}function CC(){const[,e]=Mh("/p/:projectId/new"),[,r]=lr(),s=e==null?void 0:e.projectId,i=Ce(h=>h.createSession),c=Ce(h=>h.resetPendingSessionCreate),u=P.useCallback(async()=>{if(!s)return;const h=await i(s);h?(r(`/p/${s}/s/${h.id}`),c()):(r(`/p/${s}`),c())},[s,i,r,c]);return P.useEffect(()=>{u()},[u]),o.jsx("div",{className:"flex-1 flex items-center justify-center",children:o.jsx(vo,{})})}function kC(){const e=Ft(r=>r.currentProject);return o.jsx("div",{className:"h-full flex flex-col items-center justify-center p-8 text-center",children:o.jsxs("div",{className:"max-w-md",children:[o.jsx("h2",{className:"text-xl font-semibold text-text-primary mb-2",children:(e==null?void 0:e.name)??"Project"}),o.jsx("p",{className:"text-text-secondary mb-6",children:"No session selected"}),o.jsxs("div",{className:"flex flex-col gap-3",children:[e&&o.jsx(Fn,{href:`/p/${e.id}/new`,"data-testid":"create-new-session-button",className:"block w-full rounded font-medium transition-colors bg-accent-primary/25 text-text-primary hover:bg-accent-primary/40 px-3 py-2 text-center",children:"Create New Session"}),o.jsx("p",{className:"text-sm text-text-muted",children:"Or select an existing session from the sidebar"})]})]})})}const Ga=e=>Math.round(e*10)/10;function mh(e){return{providerId:e.providerId,providerName:e.providerName,backend:e.backend,model:e.model}}function EC(e){return`${e.providerId}::${e.model}`}function jC(e){return`${e.providerName} > ${e.model}`}function ob(e){let r=0,s=0,i=0,c=0,u=0,h=0;const l=[],d=[];let f=0;for(const[v,S]of e.entries()){const k=S.stats,C=mh(k);r+=k.totalTime,s+=k.toolTime,i+=k.prefillTokens,c+=k.generationTokens;const y=k.prefillSpeed>0?k.prefillTokens/k.prefillSpeed:0,b=k.generationSpeed>0?k.generationTokens/k.generationSpeed:0;u+=y,h+=b,l.push({messageId:S.id,timestamp:S.timestamp,...C,mode:k.mode,responseIndex:v+1,prefillTokens:k.prefillTokens,generationTokens:k.generationTokens,prefillSpeed:k.prefillSpeed,generationSpeed:k.generationSpeed,totalTime:k.totalTime,aiTime:k.totalTime-k.toolTime,toolTime:k.toolTime});const x=k.llmCalls??[];for(const _ of x)f+=1,d.push({messageId:S.id,timestamp:_.timestamp??S.timestamp,providerId:_.providerId,providerName:_.providerName,backend:_.backend,model:_.model,mode:k.mode,responseIndex:v+1,sessionCallIndex:f,callIndex:_.callIndex,promptTokens:_.promptTokens,completionTokens:_.completionTokens,ttft:_.ttft,completionTime:_.completionTime,prefillSpeed:_.prefillSpeed,generationSpeed:_.generationSpeed,totalTime:_.totalTime,..._.temperature!==void 0&&{temperature:_.temperature},..._.topP!==void 0&&{topP:_.topP},..._.topK!==void 0&&{topK:_.topK},..._.maxTokens!==void 0&&{maxTokens:_.maxTokens}})}const g=u>0?Ga(i/u):0,m=h>0?Ga(c/h):0;return{totalTime:Ga(r),aiTime:Ga(r-s),toolTime:Ga(s),prefillTokens:i,generationTokens:c,avgPrefillSpeed:g,avgGenerationSpeed:m,responseCount:e.length,llmCallCount:d.length,dataPoints:l,callDataPoints:d}}function NC(e){const r=e.filter(c=>c.stats!==void 0&&c.stats!==null).sort((c,u)=>new Date(c.timestamp).getTime()-new Date(u.timestamp).getTime());if(r.length===0)return null;const s=new Map;for(const c of r){const u=EC(mh(c.stats)),h=s.get(u)??[];s.set(u,[...h,c])}const i=Array.from(s.entries()).map(([c,u])=>{const h=mh(u[0].stats),l=ob(u);return{...h,key:c,label:jC(h),...l}});return{...ob(r),modelGroups:i}}function TC(e){return P.useMemo(()=>NC(e),[e])}function AC(e){const[r,s]=P.useState(null),[i,c]=P.useState(!0),[u,h]=P.useState(null),l=e||"";return P.useEffect(()=>{if(!l){c(!1);return}let d=!0,f=null;const g=async()=>{try{const v=await(await ke(`/api/branch?workdir=${encodeURIComponent(l)}`)).json();d&&(s(v.branch),h(v.error||null),c(!1))}catch(m){d&&(h(m instanceof Error?m.message:"Failed to fetch branch"),c(!1))}};return g(),f=setInterval(g,3e3),()=>{d=!1,f&&clearInterval(f)}},[l]),{branch:r,loading:i,error:u}}function Zl(e){return e.toLocaleString("en-US").replace(/,/g," ")}function lb(e){return e>=1e3?`${(e/1e3).toFixed(1)}k`:e.toFixed(1)}function DC(e){if(e<60)return`${e.toFixed(1)}s`;const r=Math.floor(e/60),s=Math.round(e%60);return`${r}m${s}s`}const cb=["▁","▂","▃","▄","▅","▆","▇","█"];function RC(e,r,s){if(s===r)return 4;const i=(e-r)/(s-r);return Math.min(7,Math.max(0,Math.round(i*7)))}function LC(e,r){if(e===r){const c=Math.max(Math.abs(e)*.05,1);return{minY:e-c,maxY:r+c}}const s=r-e,i=Math.max(s*.1,.1);return{minY:e-i,maxY:r+i}}function OC(e,r){if(e.length===0||r<=0)return{blocks:"",minX:0,maxX:0,minY:0,maxY:0};const s=[...e].sort((m,v)=>m.x-v.x),i=s[0].x,c=s[s.length-1].x,u=Math.min(...s.map(m=>m.y)),h=Math.max(...s.map(m=>m.y)),{minY:l,maxY:d}=LC(u,h),f=Array.from({length:r},()=>" "),g=new Map;for(const m of s){const v=c===i?0:Math.round((m.x-i)/(c-i)*(r-1)),S=g.get(v)??[];g.set(v,[...S,m.y])}for(const[m,v]of g){const S=Math.max(...v);f[m]=cb[RC(S,l,d)]??cb[0]}return{blocks:f.join(""),minX:i,maxX:c,minY:l,maxY:d}}function ub(e){return e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${(e/1e3).toFixed(1)}k`:e.toFixed(1)}function db({data:e,width:r=60,height:s=78,label:i,xLabel:c,yLabel:u,showAxes:h=!0,formatY:l=ub,formatX:d=ub}){const f=P.useMemo(()=>{const g=OC(e,r),m=Math.max(r*6,240),v=10,S=8,C=[...e].sort((_,j)=>_.x-j.x).map(_=>{const j=g.maxX===g.minX?m/2:v+(_.x-g.minX)/(g.maxX-g.minX)*(m-v*2),A=g.maxY===g.minY?s/2:S+(g.maxY-_.y)/(g.maxY-g.minY)*(s-S*2);return{..._,cx:j,cy:A,leftPercent:j/m*100,topPercent:A/s*100}}),y=C.map((_,j)=>`${j===0?"M":"L"} ${_.cx.toFixed(1)} ${_.cy.toFixed(1)}`).join(" "),x=[g.maxY,(g.maxY+g.minY)/2,g.minY].map(_=>({value:_,y:g.maxY===g.minY?s/2:S+(g.maxY-_)/(g.maxY-g.minY)*(s-S*2)}));return{...g,chartWidth:m,points:C,path:y,gridLines:x}},[e,s,r]);return e.length===0?o.jsxs("div",{className:"font-mono text-text-muted text-xs",children:[i&&o.jsx("div",{className:"mb-1",children:i}),o.jsx("div",{children:"No data"})]}):o.jsxs("div",{className:"font-mono text-xs",children:[i&&o.jsx("div",{className:"text-text-secondary mb-2",children:i}),o.jsxs("div",{className:"flex gap-3",children:[h&&o.jsx("div",{className:"w-12 h-[78px] flex flex-col justify-between text-right text-text-muted",children:f.gridLines.map(g=>o.jsx("span",{children:l(g.value)},`${g.value}-${g.y}`))}),o.jsx("div",{className:"flex-1 min-w-0",children:o.jsxs("div",{className:"relative h-[78px]",children:[o.jsxs("svg",{viewBox:`0 0 ${f.chartWidth} ${s}`,className:"w-full h-[78px] overflow-visible",preserveAspectRatio:"none","aria-hidden":"true",children:[f.gridLines.map(g=>o.jsx("line",{x1:"0",x2:f.chartWidth,y1:g.y,y2:g.y,stroke:"currentColor",strokeDasharray:"3 4",className:"text-border/60"},`grid-${g.y}`)),f.points.map(g=>o.jsx("line",{x1:g.cx,x2:g.cx,y1:s-4,y2:g.cy,stroke:"currentColor",className:"text-border/40"},`guide-${g.cx}-${g.cy}`)),f.points.length>1&&o.jsx("path",{d:f.path,fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:"text-accent-primary/45"})]}),f.points.map(g=>o.jsx("div",{className:"absolute -translate-x-1/2 -translate-y-1/2",style:{left:`${g.leftPercent}%`,top:`${g.topPercent}%`},title:`${d(g.x)} -> ${l(g.y)}`,children:o.jsx("div",{className:"w-2.5 h-2.5 rounded-full bg-accent-primary/20 flex items-center justify-center",children:o.jsx("div",{className:"w-1.5 h-1.5 rounded-full bg-accent-primary"})})},`point-${g.x}-${g.y}`))]})})]}),h&&o.jsxs("div",{className:"flex items-start gap-3 text-text-muted mt-1",children:[o.jsx("span",{className:"w-12"}),o.jsxs("span",{className:"flex-1 flex justify-between",children:[o.jsx("span",{children:d(f.minX)}),o.jsx("span",{children:c}),o.jsx("span",{children:d(f.maxX)})]})]}),u&&h&&o.jsx("div",{className:"text-text-muted mt-1 text-center",children:u})]})}function MC({data:e,prefillLabel:r="Prefill Speed (tok/s) by Response",generationLabel:s="Generation Speed (tok/s) by Response",xLabel:i="response",width:c=60}){const u=e.map(l=>({x:l.x,y:l.ppSpeed})),h=e.map(l=>({x:l.x,y:l.tgSpeed}));return o.jsxs("div",{className:"space-y-5",children:[o.jsx(db,{data:u,width:c,label:r,xLabel:i}),o.jsx(db,{data:h,width:c,label:s,xLabel:i})]})}function IC(e){const r=new Map;for(const s of e.callDataPoints){const i=r.get(s.messageId)??[];r.set(s.messageId,[...i,s])}return e.dataPoints.map(s=>{const i=[...r.get(s.messageId)??[]].sort((c,u)=>c.callIndex-u.callIndex);return{...s,callCount:i.length,calls:i,isExpandable:i.length>1}})}function BC(e){return{mode:"responses",xLabel:"response",prefillLabel:"Prefill Speed (tok/s) by Response",generationLabel:"Generation Speed (tok/s) by Response",points:e.dataPoints.map(r=>({x:r.responseIndex,ppSpeed:r.prefillSpeed,tgSpeed:r.generationSpeed}))}}function zC(e){return{mode:"calls",xLabel:"context",prefillLabel:"Prefill Speed (tok/s) vs Context",generationLabel:"Generation Speed (tok/s) vs Context",points:e.callDataPoints.map(r=>({x:r.promptTokens,ppSpeed:r.prefillSpeed,tgSpeed:r.generationSpeed}))}}function PC(e){return e.callDataPoints.length>0?zC(e):BC(e)}function qd(e){if(e<60)return`${e.toFixed(1)}s`;const r=Math.floor(e/60),s=e%60;return`${r}m ${s.toFixed(0)}s`}function $s(e){return e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${(e/1e3).toFixed(1)}k`:e.toString()}function to(e){return e>=1e3?`${(e/1e3).toFixed(1)}k`:e.toFixed(1)}function HC(e){if(e.length===0)return"0 ctx";const r=Math.min(...e),s=Math.max(...e);return r===s?`${$s(r)} ctx`:`${$s(r)}-${$s(s)} ctx`}function Ql(e){return`${to(e)} t/s`}function ly(e){try{return new Date(e).toLocaleTimeString("en-US",{hour12:!1})}catch{return e}}function FC(e){return{exportedAt:new Date().toISOString(),providerId:e.providerId,providerName:e.providerName,backend:e.backend,model:e.model,label:e.label,summary:{totalTime:e.totalTime,aiTime:e.aiTime,toolTime:e.toolTime,prefillTokens:e.prefillTokens,generationTokens:e.generationTokens,avgPrefillSpeed:e.avgPrefillSpeed,avgGenerationSpeed:e.avgGenerationSpeed,responseCount:e.responseCount,llmCallCount:e.llmCallCount},responses:e.dataPoints.map(r=>({responseIndex:r.responseIndex,timestamp:r.timestamp,mode:r.mode,prefillTokens:r.prefillTokens,generationTokens:r.generationTokens,prefillSpeed:r.prefillSpeed,generationSpeed:r.generationSpeed,totalTime:r.totalTime,aiTime:r.aiTime,toolTime:r.toolTime})),llmCalls:e.callDataPoints.map(r=>({sessionCallIndex:r.sessionCallIndex,responseIndex:r.responseIndex,callIndex:r.callIndex,timestamp:r.timestamp,mode:r.mode,promptTokens:r.promptTokens,completionTokens:r.completionTokens,ttft:r.ttft,completionTime:r.completionTime,prefillSpeed:r.prefillSpeed,generationSpeed:r.generationSpeed,totalTime:r.totalTime}))}}function UC({isOpen:e,onClose:r,stats:s}){const i=P.useRef(null),[c,u]=P.useState({}),[h,l]=P.useState(()=>{var k;return((k=s.modelGroups[0])==null?void 0:k.key)??""});P.useEffect(()=>{var k;s.modelGroups.some(C=>C.key===h)||l(((k=s.modelGroups[0])==null?void 0:k.key)??"")},[h,s.modelGroups]);const d=P.useMemo(()=>s.modelGroups.find(k=>k.key===h)??s.modelGroups[0],[h,s.modelGroups]),f=P.useMemo(()=>d?IC(d):[],[d]),g=P.useMemo(()=>d?PC(d):{mode:"responses",xLabel:"response",prefillLabel:"",generationLabel:"",points:[]},[d]),m=P.useCallback(k=>{u(C=>({...C,[k]:!C[k]}))},[]),v=P.useCallback(()=>{if(!d)return;const k=FC(d);navigator.clipboard.writeText(JSON.stringify(k,null,2)).catch(C=>console.error("Failed to copy:",C))},[d]),S=P.useCallback(async()=>{if(i.current)try{const k=(await fh(async()=>{const{default:b}=await import("./html2canvas.esm-QH1iLAAe.js");return{default:b}},[])).default,C=await k(i.current,{backgroundColor:"#1a1a1a",scale:2}),y=document.createElement("a");y.download=`openfox-stats-${new Date().toISOString().slice(0,10)}.png`,y.href=C.toDataURL("image/png"),y.click()}catch(k){console.error("Failed to export PNG:",k),v()}},[v]);return o.jsx(At,{isOpen:e,onClose:r,title:"Session Stats",size:"lg",children:o.jsxs("div",{ref:i,className:"space-y-6",children:[o.jsx("section",{children:o.jsx("div",{className:"flex flex-wrap gap-2",children:s.modelGroups.map(k=>o.jsx("button",{onClick:()=>l(k.key),className:`px-3 py-1.5 rounded border text-xs transition-colors ${k.key===(d==null?void 0:d.key)?"border-accent-primary bg-accent-primary/10 text-accent-primary":"border-border text-text-muted hover:text-text-primary hover:bg-bg-tertiary/40"}`,title:k.label,children:k.label},k.key))})}),d&&o.jsxs("section",{children:[o.jsx("h3",{className:"text-sm font-semibold text-text-secondary mb-3 uppercase tracking-wide",children:"Summary"}),o.jsxs("div",{className:"grid grid-cols-2 md:grid-cols-5 gap-4",children:[o.jsx(Hr,{label:"AI Time",value:qd(d.aiTime)}),o.jsx(Hr,{label:"Total Time",value:qd(d.totalTime)}),o.jsx(Hr,{label:"Tool Time",value:qd(d.toolTime)}),o.jsx(Hr,{label:"Responses",value:d.responseCount.toString()}),o.jsx(Hr,{label:"LLM Calls",value:d.llmCallCount.toString()})]}),o.jsxs("div",{className:"grid grid-cols-2 md:grid-cols-4 gap-4 mt-3",children:[o.jsx(Hr,{label:"Prefill Tokens",value:$s(d.prefillTokens),subValue:`@ ${to(d.avgPrefillSpeed)} tok/s`}),o.jsx(Hr,{label:"Gen Tokens",value:$s(d.generationTokens),subValue:`@ ${to(d.avgGenerationSpeed)} tok/s`}),o.jsx(Hr,{label:"Avg PP Speed",value:`${to(d.avgPrefillSpeed)}`,subValue:"tok/s"}),o.jsx(Hr,{label:"Avg TG Speed",value:`${to(d.avgGenerationSpeed)}`,subValue:"tok/s"})]})]}),d&&g.points.length>1&&o.jsxs("section",{children:[o.jsxs("div",{className:"flex items-center justify-between mb-3",children:[o.jsx("h3",{className:"text-sm font-semibold text-text-secondary uppercase tracking-wide",children:"Performance Progression"}),o.jsxs("div",{className:"flex items-center gap-2",children:[o.jsx("button",{onClick:v,className:"px-2 py-1 text-xs text-text-muted hover:text-text-primary hover:bg-bg-tertiary rounded transition-colors",children:"Copy JSON"}),o.jsx("button",{onClick:S,className:"px-2 py-1 text-xs text-text-muted hover:text-text-primary hover:bg-bg-tertiary rounded transition-colors",children:"Save PNG"})]})]}),o.jsx("div",{className:"bg-bg-tertiary/50 rounded p-4",children:o.jsx(MC,{data:g.points,width:50,prefillLabel:g.prefillLabel,generationLabel:g.generationLabel,xLabel:g.xLabel})})]}),d&&o.jsxs("section",{children:[o.jsxs("h3",{className:"text-sm font-semibold text-text-secondary mb-3 uppercase tracking-wide",children:["Response Log (",d.responseCount," responses)"]}),o.jsx("div",{className:"overflow-y-auto bg-bg-tertiary/30 rounded",children:o.jsxs("table",{className:"w-full table-fixed border-separate border-spacing-0 text-xs",children:[o.jsxs("colgroup",{children:[o.jsx("col",{className:"w-[7%]"}),o.jsx("col",{className:"w-[14%]"}),o.jsx("col",{className:"w-[10%]"}),o.jsx("col",{className:"w-[14%]"}),o.jsx("col",{className:"w-[14%]"}),o.jsx("col",{className:"w-[14%]"}),o.jsx("col",{className:"w-[11%]"}),o.jsx("col",{className:"w-[2%]"})]}),o.jsx("thead",{children:o.jsxs("tr",{className:"text-[10px] uppercase tracking-wide text-text-muted/80",children:[o.jsx("th",{className:"px-3 py-2 text-center font-medium",children:"#"}),o.jsx("th",{className:"px-2 py-2 text-center font-medium",children:"At"}),o.jsx("th",{className:"px-2 py-2 text-center font-medium",children:"Time"}),o.jsx("th",{className:"px-2 py-2 text-center font-medium",children:"Context"}),o.jsx("th",{className:"px-2 py-2 text-center font-medium",children:"PP t/s"}),o.jsx("th",{className:"px-2 py-2 text-center font-medium",children:"TG t/s"}),o.jsx("th",{className:"px-2 py-2 text-center font-medium",children:"Calls"}),o.jsx("th",{className:"px-2 py-2"})]})}),o.jsx("tbody",{children:f.map((k,C)=>o.jsxs(P.Fragment,{children:[o.jsx($C,{row:k,index:C,isExpanded:c[k.messageId]??!1,onToggle:k.isExpandable?()=>m(k.messageId):void 0}),(c[k.messageId]??!1)&&k.calls.map((y,b)=>o.jsx(qC,{dataPoint:y,index:b},`${y.messageId}-${y.callIndex}`))]},k.messageId))})]})})]})]})})}function Hr({label:e,value:r,subValue:s}){return o.jsxs("div",{className:"bg-bg-tertiary/50 rounded p-3",children:[o.jsx("div",{className:"text-text-muted text-xs mb-1",children:e}),o.jsx("div",{className:"text-text-primary text-lg font-semibold",children:r}),s&&o.jsx("div",{className:"text-text-muted text-xs",children:s})]})}function $C({row:e,index:r,isExpanded:s,onToggle:i}){const c=e.calls.length>0?HC(e.calls.map(u=>u.promptTokens)):`${$s(e.prefillTokens)} ctx`;return o.jsxs("tr",{onClick:i,className:`${r%2===0?"bg-bg-tertiary/20":""} ${i?"cursor-pointer hover:bg-bg-tertiary/35 transition-colors":""}`,children:[o.jsx("td",{className:"px-3 py-2 text-center text-text-muted align-middle",children:e.responseIndex}),o.jsx("td",{className:"px-2 py-2 text-center text-text-muted font-mono align-middle whitespace-nowrap",children:ly(e.timestamp)}),o.jsxs("td",{className:"px-2 py-2 text-center text-text-muted align-middle whitespace-nowrap",children:[e.totalTime.toFixed(1),"s"]}),o.jsx("td",{className:"px-2 py-2 text-center text-text-primary font-mono align-middle whitespace-nowrap",children:c.replace(/ ctx$/,"")}),o.jsx("td",{className:"px-2 py-2 text-center text-text-primary font-mono align-middle whitespace-nowrap",children:Ql(e.prefillSpeed)}),o.jsx("td",{className:"px-2 py-2 text-center text-text-primary font-mono align-middle whitespace-nowrap",children:Ql(e.generationSpeed)}),o.jsx("td",{className:"px-2 py-2 text-center text-text-muted font-mono align-middle whitespace-nowrap",children:e.callCount}),o.jsx("td",{className:"px-2 py-2 text-center text-text-muted align-middle whitespace-nowrap",children:e.isExpandable?s?"v":">":""})]})}function qC({dataPoint:e,index:r}){const s=e.temperature!==void 0||e.topP!==void 0||e.topK!==void 0||e.maxTokens!==void 0;return o.jsxs(o.Fragment,{children:[o.jsxs("tr",{className:`${r%2===0?"bg-bg-tertiary/10":"bg-bg-tertiary/5"}`,children:[o.jsxs("td",{className:"px-3 py-2 pl-6 text-center text-text-muted align-middle border-l border-border/60",children:["c",e.callIndex]}),o.jsx("td",{className:"px-2 py-2 text-center text-text-muted font-mono align-middle whitespace-nowrap",children:ly(e.timestamp)}),o.jsxs("td",{className:"px-2 py-2 text-center text-text-muted align-middle whitespace-nowrap",children:[e.totalTime.toFixed(1),"s"]}),o.jsx("td",{className:"px-2 py-2 text-center text-text-primary font-mono align-middle whitespace-nowrap",children:$s(e.promptTokens)}),o.jsx("td",{className:"px-2 py-2 text-center text-text-primary font-mono align-middle whitespace-nowrap",children:Ql(e.prefillSpeed)}),o.jsx("td",{className:"px-2 py-2 text-center text-text-primary font-mono align-middle whitespace-nowrap",children:Ql(e.generationSpeed)}),o.jsx("td",{className:"px-2 py-2 text-center text-text-muted font-mono align-middle whitespace-nowrap",children:e.callIndex}),o.jsx("td",{className:"px-2 py-2"})]}),s&&o.jsx("tr",{className:`${r%2===0?"bg-bg-tertiary/5":"bg-bg-tertiary/[2.5%]"}`,children:o.jsx("td",{colSpan:8,className:"px-6 py-1.5 border-l border-border/60",children:o.jsxs("div",{className:"flex flex-wrap gap-x-4 gap-y-1 text-[10px] text-text-muted",children:[e.temperature!==void 0&&o.jsxs("span",{children:["temp: ",e.temperature.toFixed(2)]}),e.topP!==void 0&&o.jsxs("span",{children:["topP: ",e.topP.toFixed(2)]}),e.topK!==void 0&&o.jsxs("span",{children:["topK: ",e.topK]}),e.maxTokens!==void 0&&o.jsxs("span",{children:["maxTok: ",e.maxTokens]})]})})})]})}const WC={pending:{icon:"○",color:"text-text-muted",label:"Pending"},in_progress:{icon:"●",color:"text-accent-warning",label:"In Progress",animate:!0},completed:{icon:"◉",color:"text-purple-400",label:"Completed"},passed:{icon:"✓",color:"text-accent-success",label:"Passed"},failed:{icon:"✗",color:"text-accent-error",label:"Failed"}},VC=P.memo(function({criteria:r}){if(r.length===0)return o.jsx("div",{className:"text-text-muted text-sm text-center py-2",children:"No criteria yet"});const s={pending:0,in_progress:0,completed:0,passed:0,failed:0};for(const c of r){const u=c.status.type;u in s&&s[u]++}const i=Object.keys(s).filter(c=>s[c]>0);return o.jsxs("div",{className:"space-y-1",children:[o.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[o.jsx("span",{className:"font-semibold text-text-primary",children:"Total:"}),o.jsx("span",{className:"text-text-secondary",children:r.length})]}),o.jsx("div",{className:"space-y-1",children:i.map(c=>{const u=WC[c];return o.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[o.jsx("span",{className:`${u.color} ${u.animate?"animate-pulse":""} text-sm leading-tight`,children:u.icon}),o.jsxs("span",{className:"text-text-muted",children:[u.label,":"]}),o.jsx("span",{className:"text-text-primary font-medium",children:s[c]})]},c)})})]})});function GC({isOpen:e,onClose:r}){const s=gr(C=>C.config),i=gr(C=>C.saveConfig),[c,u]=P.useState(""),[h,l]=P.useState(""),[d,f]=P.useState(!1),[g,m]=P.useState(!1),[v,S]=P.useState(!1);P.useEffect(()=>{e&&(u((s==null?void 0:s.command)??""),l((s==null?void 0:s.url)??""),f((s==null?void 0:s.hotReload)??!1),m((s==null?void 0:s.disableInspect)??!1))},[e,s]);const k=async()=>{!c.trim()||!h.trim()||(S(!0),await i({command:c.trim(),url:h.trim(),hotReload:d,disableInspect:g}),S(!1),r())};return o.jsx(At,{isOpen:e,onClose:r,title:"Dev Server Config",size:"sm",children:o.jsxs("div",{className:"space-y-4",children:[o.jsxs("div",{children:[o.jsx("label",{className:"block text-xs text-text-secondary mb-1",children:"Command"}),o.jsx("input",{className:"input w-full",type:"text",value:c,onChange:C=>u(C.target.value),placeholder:"npm run dev"})]}),o.jsxs("div",{children:[o.jsx("label",{className:"block text-xs text-text-secondary mb-1",children:"Dev URL"}),o.jsx("input",{className:"input w-full",type:"text",value:h,onChange:C=>l(C.target.value),placeholder:"http://localhost:3000"})]}),o.jsxs("div",{className:"flex items-center gap-2",children:[o.jsx("input",{type:"checkbox",id:"hotReload",checked:d,onChange:C=>f(C.target.checked),className:"rounded border-border bg-bg-tertiary"}),o.jsx("label",{htmlFor:"hotReload",className:"text-xs text-text-secondary",children:"Hot Reload"})]}),o.jsxs("div",{className:"flex items-center gap-2",children:[o.jsx("input",{type:"checkbox",id:"disableInspect",checked:g,onChange:C=>m(C.target.checked),className:"rounded border-border bg-bg-tertiary"}),o.jsx("label",{htmlFor:"disableInspect",className:"text-xs text-text-secondary",children:"Disable inspect feedback"})]}),o.jsxs("div",{className:"flex justify-end gap-2 pt-2",children:[o.jsx("button",{className:"btn btn-secondary",onClick:r,children:"Cancel"}),o.jsx("button",{className:"btn btn-primary",onClick:k,disabled:v||!c.trim()||!h.trim(),children:v?"Saving...":"Save"})]})]})})}const hb={30:"text-black",31:"text-red-400",32:"text-accent-success",33:"text-accent-warning",34:"text-blue-400",35:"text-purple-400",36:"text-cyan-400",37:"text-gray-300",90:"text-gray-500",91:"text-red-500",92:"text-green-500",93:"text-yellow-400",94:"text-blue-500",95:"text-pink-400",96:"text-cyan-500",97:"text-white"},KC={40:"bg-black",41:"bg-red-900",42:"bg-green-900",43:"bg-yellow-900",44:"bg-blue-900",45:"bg-purple-900",46:"bg-cyan-900",47:"bg-gray-700"},fb={1:"font-bold",2:"opacity-75",4:"underline",7:"bg-bg-secondary"},YC="text-text-primary";function XC(e){const r=[],s=/\x1b\[([0-9;]+)m/g;let i=0,c="text-text-primary",u;try{for(;(u=s.exec(e))!==null;){if(u.index>i){const f=e.slice(i,u.index);f&&r.push({text:f,className:c})}const h=u[1];if(!h)continue;const l=h.split(";").map(Number);if(l.length===0||l[0]===0){c="text-text-primary";continue}const d=[];for(const f of l)if(f>=30&&f<=37){const g=hb[f];g&&d.push(g)}else if(f>=40&&f<=47){const g=KC[f];g&&d.push(g)}else if(f>=90&&f<=97){const g=hb[f];g&&d.push(g)}else if(f in fb){const g=fb[f];g&&d.push(g)}else f===39?d.push(YC):f===49&&(c=c.split(" ").filter(g=>!g.startsWith("bg-")).join(" "));d.length>0&&(c=d.join(" ")),i=s.lastIndex}if(i<e.length){const h=e.slice(i);h&&r.push({text:h,className:c})}return r}catch(h){return console.warn("ANSI parsing failed, stripping codes:",h),[{text:ZC(e),className:"text-text-primary"}]}}function ZC(e){return e.replace(/\x1b\[([0-9;]+)m/g,"")}function co(e){const r=XC(e),s=[];return r.forEach((i,c)=>{const u=i.text.split(`
85
85
  `);u.forEach((h,l)=>{s.push(gn.createElement("span",{key:`${c}-${l}`,className:i.className,style:{display:"inline-block",whiteSpace:"pre-wrap"}},h)),l<u.length-1&&s.push(gn.createElement("br",{key:`${c}-${l}-br`}))})}),s.length===1?s[0]:s}const cy=P.memo(function({title:r,logs:s,onClose:i,preClassName:c}){const u=P.useRef(null);return P.useEffect(()=>{u.current&&(u.current.scrollTop=u.current.scrollHeight)},[s]),o.jsx(At,{isOpen:!0,onClose:i,title:r,size:"full",children:o.jsx("pre",{ref:u,className:c,children:s.length===0?o.jsx("span",{className:"text-text-muted",children:"No output yet"}):s.map((h,l)=>o.jsx("span",{className:h.stream==="stderr"?"text-accent-warning":"",children:co(h.content)},l))})})}),QC=P.memo(function({logs:r,anchorRef:s,isHiding:i,onExpand:c,onClose:u}){const[h,l]=P.useState(null),d=P.useRef(null);return P.useEffect(()=>{var g;const f=(g=s.current)==null?void 0:g.getBoundingClientRect();f&&l({bottom:window.innerHeight-f.bottom,right:window.innerWidth-f.right,width:f.width,height:f.height})},[s]),P.useEffect(()=>{d.current&&(d.current.scrollTop=d.current.scrollHeight)},[r]),h?o.jsxs("div",{className:"relative",children:[o.jsx("pre",{ref:d,className:"fixed z-50 text-sm font-mono text-text-primary bg-bg-primary p-2 rounded border border-border overflow-auto transition-all duration-150 ease-out select-text",style:{bottom:h.bottom,right:h.right,width:h.width*2,maxHeight:h.height*3,transformOrigin:"bottom right",transform:i?"scale(0.01)":"scale(1)",opacity:i?0:1},children:r.map((f,g)=>o.jsx("span",{className:f.stream==="stderr"?"text-accent-warning":"",children:co(f.content)},g))}),o.jsx("button",{onClick:()=>{u(),c()},className:"fixed z-50 px-2 py-1 rounded text-xs font-medium bg-accent-primary/30 text-text-primary hover:bg-accent-primary/50 transition-colors duration-150",style:{bottom:h.bottom+8,right:h.right+8},children:"Expand"})]}):null}),JC=P.memo(function({workdir:r}){const s=gr(V=>V.setWorkdir),i=gr(V=>V.status),c=gr(V=>V.config),u=gr(V=>V.logs),h=gr(V=>V.start),l=gr(V=>V.stop),d=gr(V=>V.fetchLogs),f=Ce(V=>V.currentSession),[g,m]=P.useState(!1),[v,S]=P.useState(!1),[k,C]=P.useState(!1),[y,b]=P.useState(!1),x=P.useRef(null),_=P.useRef(null),j=P.useRef(null),A=P.useRef(null),N=P.useRef(null),D=()=>{const V=i==null?void 0:i.inspectProxyPort;if(!V){i!=null&&i.url&&window.open(i.url,"_blank");return}const W=`${window.location.protocol}//${window.location.hostname}:${V}`,I=window.open(W,"_blank");if(I){N.current=I;const $=()=>{var X;!N.current||N.current.closed||(N.current.postMessage({type:"setFoxSessionId",sessionId:(f==null?void 0:f.id)??null},"*"),N.current.postMessage({type:"setFoxSessionTitle",sessionTitle:((X=f==null?void 0:f.metadata)==null?void 0:X.title)??null},"*"),N.current.postMessage({type:"setFoxInspectEnabled",enabled:!(c!=null&&c.disableInspect)},"*"))},B=setInterval(()=>{$(),(!N.current||N.current.closed)&&clearInterval(B)},500);setTimeout(()=>clearInterval(B),5e3)}},T=(i==null?void 0:i.state)??"off",z=c!==null,O=T==="running"||T==="warning";P.useEffect(()=>{s(r??null)},[r,s]),P.useEffect(()=>{O&&d()},[O,d]),P.useEffect(()=>{j.current&&O&&(j.current.scrollTop=j.current.scrollHeight)},[u,O]);const q=()=>{O?l():h()};return o.jsxs("div",{className:"mt-2 pt-3 border-t border-border space-y-3",children:[o.jsxs("div",{className:"flex items-center justify-between",children:[o.jsxs("div",{className:"flex items-center gap-2",children:[o.jsx("span",{className:`inline-block w-2.5 h-2.5 rounded-full flex-shrink-0 ${T==="running"?"bg-accent-success":T==="warning"?"bg-accent-warning":T==="error"?"bg-accent-error":"bg-text-muted"}`}),o.jsx("h3",{className:"text-sm font-semibold text-text-primary",children:"Dev Server"})]}),o.jsx("button",{onClick:()=>m(!0),className:"p-1.5 rounded hover:bg-bg-tertiary transition-colors text-text-muted",title:"Configure dev server",children:o.jsx(yw,{})})]}),z?o.jsxs(o.Fragment,{children:[T==="running"||T==="warning"?o.jsxs("div",{className:"flex gap-2",children:[o.jsxs("button",{onClick:q,className:"flex-1 flex items-center justify-center gap-1.5 rounded font-medium text-sm px-3 py-1.5 bg-bg-tertiary text-text-primary hover:bg-border transition-colors",children:[o.jsx(Tw,{}),"Stop"]}),(i==null?void 0:i.url)&&o.jsxs("button",{onClick:()=>D(),className:"flex-1 flex items-center justify-center gap-1.5 rounded font-medium text-sm px-3 py-1.5 bg-accent-primary/25 text-text-primary hover:bg-accent-primary/40 transition-colors",title:i.url,children:[o.jsx(ww,{}),"Open"]})]}):o.jsx("button",{onClick:q,className:"w-full rounded font-medium text-sm px-3 py-1.5 bg-accent-primary/25 text-text-primary hover:bg-accent-primary/40 transition-colors",children:"Start"}),O&&o.jsxs("div",{ref:A,className:"relative",onMouseEnter:()=>{_.current&&clearTimeout(_.current),x.current=setTimeout(()=>{C(!0),b(!1)},500)},onMouseLeave:()=>{x.current&&clearTimeout(x.current),b(!0),_.current=setTimeout(()=>C(!1),150)},children:[o.jsx("pre",{ref:j,className:"text-sm bg-bg-primary p-2 rounded overflow-auto max-h-[200px] border border-border",children:u.length===0?o.jsx("span",{className:"text-text-muted",children:"No output yet"}):u.map((V,W)=>o.jsx("span",{className:V.stream==="stderr"?"text-accent-warning":"",children:co(V.content)},W))}),(k||y)&&A.current&&Ki.createPortal(o.jsx(QC,{logs:u,anchorRef:A,isHiding:y,onExpand:()=>S(!0),onClose:()=>C(!1)}),document.body)]})]}):o.jsx("button",{onClick:()=>m(!0),className:"w-full rounded font-medium text-sm px-3 py-1.5 bg-bg-tertiary text-text-muted hover:bg-border transition-colors",children:"Configure"}),o.jsx(GC,{isOpen:g,onClose:()=>m(!1)}),v&&o.jsx(cy,{title:"Dev Server Logs",logs:u,onClose:()=>S(!1)})]})}),e2=P.memo(function({sessionId:r}){var S;const s=no(k=>k.processes),i=no(k=>k.stopProcess),[c,u]=P.useState(null),[h,l]=P.useState([]),d=s.filter(k=>k.status!=="exited"),f=d.filter(k=>k.status==="running").length;if(s.length===0)return null;const g=k=>{switch(k){case"running":return"bg-accent-success";case"starting":return"bg-accent-warning";case"stopping":return"bg-accent-warning";case"exited":return"bg-text-muted";default:return"bg-text-muted"}},m=k=>{const C=no.getState().logs[k]??[];l(C.map(y=>({content:y.content,stream:y.stream}))),u(k)},v=k=>{r&&i(k,r)};return o.jsxs("div",{className:"mt-2 pt-3 border-t border-border space-y-3",children:[o.jsx("div",{className:"flex items-center justify-between",children:o.jsxs("div",{className:"flex items-center gap-2",children:[o.jsx("span",{className:"inline-block w-2.5 h-2.5 rounded-full flex-shrink-0 bg-accent-primary"}),o.jsx("h3",{className:"text-sm font-semibold text-text-primary",children:"Background"}),o.jsxs("span",{className:"text-xs text-text-muted",children:["(",f," running)"]})]})}),o.jsx("div",{className:"space-y-2",children:d.map(k=>o.jsx("div",{className:"border border-border rounded p-2",children:o.jsxs("div",{className:"flex items-center justify-between",children:[o.jsxs("div",{className:"flex items-center gap-2 min-w-0 flex-1",children:[o.jsx("span",{className:`inline-block w-2 h-2 rounded-full flex-shrink-0 ${g(k.status)}`}),o.jsx("span",{className:"text-sm text-text-primary truncate",title:k.name,children:k.name}),o.jsxs("span",{className:"text-xs text-text-muted",children:["[",k.status,"]"]})]}),o.jsxs("div",{className:"flex gap-1 ml-2",children:[o.jsx("button",{onClick:()=>m(k.id),className:"px-2 py-1 text-xs rounded bg-bg-tertiary hover:bg-border text-text-secondary transition-colors",title:"View logs",children:"Logs"}),o.jsx("button",{onClick:()=>v(k.id),className:"px-2 py-1 text-xs rounded bg-bg-tertiary hover:bg-accent-error/20 text-text-secondary hover:text-accent-error transition-colors",title:"Stop process",children:"Stop"})]})]})},k.id))}),c&&o.jsx(cy,{title:((S=d.find(k=>k.id===c))==null?void 0:S.name)??"",logs:h,onClose:()=>{u(null),l([])}})]})});function pb({summary:e,messages:r,workdir:s}){const[i,c]=P.useState(!1),u=TC(r),{branch:h}=AC(s),l=Rt(f=>f.version),d=Ce(f=>f.currentSession);return o.jsxs("div",{className:"flex flex-col h-full",children:[u&&o.jsxs("div",{className:"mb-4",children:[o.jsx("button",{onClick:()=>c(!0),className:"w-full flex items-center justify-center px-3 py-2 rounded bg-bg-tertiary hover:bg-bg-secondary transition-colors",title:"View detailed response and call-level stats",children:o.jsxs("div",{className:"flex items-center gap-2 text-sm text-text-muted",children:[o.jsx("span",{className:"text-text-secondary",children:DC(u.aiTime)}),o.jsx("span",{className:"w-px h-3 bg-border"}),o.jsx("span",{className:"text-text-secondary",children:lb(u.avgPrefillSpeed)}),o.jsx("span",{children:"pp"}),o.jsx("span",{className:"w-px h-3 bg-border"}),o.jsx("span",{className:"text-text-secondary",children:lb(u.avgGenerationSpeed)}),o.jsx("span",{children:"tg"})]})}),o.jsx(UC,{isOpen:i,onClose:()=>c(!1),stats:u})]}),o.jsxs("div",{className:"flex flex-col flex-1 overflow-y-auto",children:[o.jsx("div",{className:"flex items-center justify-between mb-2",children:o.jsx("h3",{className:"text-sm font-semibold text-text-primary",children:"Summary"})}),e?o.jsx("p",{className:"text-sm text-text-primary leading-relaxed",children:e}):o.jsx("div",{className:"text-text-muted text-sm text-center py-2",children:"No summary yet"}),o.jsxs("div",{className:"mt-4",children:[o.jsx("h3",{className:"text-sm font-semibold text-text-primary mb-2",children:"Progress"}),o.jsx(VC,{criteria:(d==null?void 0:d.criteria)??[]})]})]}),h&&o.jsxs("div",{className:"mt-4 flex items-center gap-2 text-sm",children:[o.jsx(mw,{}),o.jsx("span",{className:"truncate text-text-secondary",title:h,children:h})]}),o.jsx(JC,{workdir:s}),o.jsx(e2,{sessionId:d==null?void 0:d.id}),l&&o.jsxs("div",{className:"mt-4 pt-4 border-t border-border text-center text-xs text-text-muted",children:[o.jsx("a",{href:"https://github.com/co-l/openfox",target:"_blank",rel:"noopener noreferrer",className:"hover:text-accent-primary transition-colors",children:"OpenFox"})," - ",o.jsxs("span",{children:["v",l]})]})]})}function t2({children:e,criteriaSidebarOpen:r=!0,onCriteriaSidebarToggle:s,messages:i}){const c=Ce(u=>u.currentSession);return o.jsxs("div",{className:"relative h-full overflow-hidden",children:[r&&o.jsx("div",{className:"fixed md:hidden inset-0 bg-secondary/50 z-40",onClick:s}),o.jsxs("div",{className:"flex h-full",children:[o.jsx("div",{className:"flex-1 min-w-0 flex flex-col overflow-hidden bg-secondary",children:e}),r?o.jsx("aside",{className:"hidden md:block w-[320px] shrink-0 border-l border-border p-4 overflow-y-auto bg-secondary",children:o.jsx(pb,{summary:(c==null?void 0:c.summary)??null,messages:i,workdir:c==null?void 0:c.workdir})}):o.jsx("aside",{className:"hidden md:block w-0 shrink-0 overflow-hidden border-l-0"}),o.jsx("aside",{className:`
86
86
  md:hidden
87
87
  p-4 overflow-y-auto bg-secondary
@@ -5,7 +5,7 @@
5
5
  <link rel="icon" type="image/png" href="/assets/openfox.png" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0, height=device-height" />
7
7
  <title>OpenFox</title>
8
- <script type="module" crossorigin src="/assets/index-9GgVgB7B.js"></script>
8
+ <script type="module" crossorigin src="/assets/index-CWdKiSP8.js"></script>
9
9
  <link rel="stylesheet" crossorigin href="/assets/index-D4Si0Pmc.css">
10
10
  <link rel="manifest" href="/manifest.webmanifest"><script id="vite-plugin-pwa:register-sw" src="/registerSW.js"></script></head>
11
11
  <body class="bg-bg-primary text-text-primary font-mono">
package/dist/web/sw.js CHANGED
@@ -1 +1 @@
1
- if(!self.define){let e,s={};const i=(i,n)=>(i=new URL(i+".js",n).href,s[i]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=i,e.onload=s,document.head.appendChild(e)}else e=i,importScripts(i),s()}).then(()=>{let e=s[i];if(!e)throw new Error(`Module ${i} didn’t register its module`);return e}));self.define=(n,r)=>{const t=e||("document"in self?document.currentScript.src:"")||location.href;if(s[t])return;let o={};const c=e=>i(e,t),l={module:{uri:t},exports:o,require:c};s[t]=Promise.all(n.map(e=>l[e]||c(e))).then(e=>(r(...e),o))}}define(["./workbox-8c29f6e4"],function(e){"use strict";self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"registerSW.js",revision:"1872c500de691dce40960bb85481de07"},{url:"index.html",revision:"2f3c0093ed1ffff8c67eaf7f8b3edc71"},{url:"__inspect__.js",revision:"3232040b9bade73418bcfae3cb11c117"},{url:"assets/index-D4Si0Pmc.css",revision:null},{url:"assets/index-9GgVgB7B.js",revision:null},{url:"assets/html2canvas.esm-QH1iLAAe.js",revision:null},{url:"assets/openfox-192.png",revision:"79feeb86d692c274854e37959a7dae67"},{url:"assets/openfox-512.png",revision:"fee24b214220594b4f595a467e73036e"},{url:"manifest.webmanifest",revision:"c25f372c782e623ab1e768a8dfe350ca"}],{}),e.cleanupOutdatedCaches(),e.registerRoute(new e.NavigationRoute(e.createHandlerBoundToURL("index.html")))});
1
+ if(!self.define){let e,s={};const i=(i,n)=>(i=new URL(i+".js",n).href,s[i]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=i,e.onload=s,document.head.appendChild(e)}else e=i,importScripts(i),s()}).then(()=>{let e=s[i];if(!e)throw new Error(`Module ${i} didn’t register its module`);return e}));self.define=(n,r)=>{const t=e||("document"in self?document.currentScript.src:"")||location.href;if(s[t])return;let o={};const l=e=>i(e,t),c={module:{uri:t},exports:o,require:l};s[t]=Promise.all(n.map(e=>c[e]||l(e))).then(e=>(r(...e),o))}}define(["./workbox-8c29f6e4"],function(e){"use strict";self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"registerSW.js",revision:"1872c500de691dce40960bb85481de07"},{url:"index.html",revision:"f959c738a2773b1407a9f20b04cd1a2a"},{url:"__inspect__.js",revision:"3232040b9bade73418bcfae3cb11c117"},{url:"assets/index-D4Si0Pmc.css",revision:null},{url:"assets/index-CWdKiSP8.js",revision:null},{url:"assets/html2canvas.esm-QH1iLAAe.js",revision:null},{url:"assets/openfox-192.png",revision:"79feeb86d692c274854e37959a7dae67"},{url:"assets/openfox-512.png",revision:"fee24b214220594b4f595a467e73036e"},{url:"manifest.webmanifest",revision:"c25f372c782e623ab1e768a8dfe350ca"}],{}),e.cleanupOutdatedCaches(),e.registerRoute(new e.NavigationRoute(e.createHandlerBoundToURL("index.html")))});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openfox",
3
- "version": "1.6.73",
3
+ "version": "1.6.75",
4
4
  "description": "Local-LLM-first agentic coding assistant",
5
5
  "type": "module",
6
6
  "bin": {