openfox 2.0.70 → 2.0.71

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/{chat-handler-K3DWIGHG.js → chat-handler-IKLQ3ZUN.js} +11 -11
  2. package/dist/{chunk-XDWV5CYV.js → chunk-6V7DU7ID.js} +15 -20
  3. package/dist/{chunk-E4POUD2M.js → chunk-6XOA2WPU.js} +2 -2
  4. package/dist/chunk-7NMOWPNY.js +7 -0
  5. package/dist/{chunk-JHGKXQBO.js → chunk-EZK7CGJ7.js} +87 -30
  6. package/dist/{chunk-PK2RMVMB.js → chunk-I72ACQ6R.js} +19 -18
  7. package/dist/{chunk-64GN6OPR.js → chunk-NEL2REUM.js} +5 -5
  8. package/dist/{chunk-7OW6X764.js → chunk-OHGQILRF.js} +15 -4
  9. package/dist/{chunk-ZZ5JPVBT.js → chunk-OLXHRPAD.js} +38 -37
  10. package/dist/{chunk-TFCHWMOJ.js → chunk-PVUBCGAT.js} +2 -2
  11. package/dist/{chunk-QFSDJIUS.js → chunk-RKD2FML3.js} +2 -2
  12. package/dist/{chunk-YQ3MEZJL.js → chunk-TQGGMWS6.js} +2 -2
  13. package/dist/{chunk-UTSSFPYA.js → chunk-X7OCC37J.js} +5 -5
  14. package/dist/{chunk-PVWAE43V.js → chunk-Y4YESMVA.js} +50 -22
  15. package/dist/{chunk-46OR4W3L.js → chunk-Z42YTK3O.js} +17 -14
  16. package/dist/cli/dev.js +1 -1
  17. package/dist/cli/index.js +1 -1
  18. package/dist/{client-63U5CTPE.js → client-SC6X65GY.js} +3 -3
  19. package/dist/{client-pure-XHH4RRLB.js → client-pure-NMLDKRDN.js} +6 -4
  20. package/dist/{compactor-IPMMFFHM.js → compactor-MXXF5WQR.js} +4 -4
  21. package/dist/{manager-JXYRGR6B.js → manager-EHIQCIUP.js} +3 -3
  22. package/dist/{orchestrator-PUV4WG77.js → orchestrator-YGCZZNNV.js} +10 -10
  23. package/dist/package.json +2 -2
  24. package/dist/{processor-O2QW27BD.js → processor-K6UPVMIP.js} +11 -11
  25. package/dist/{provider-IBIWR4AI.js → provider-OJUCZ5RN.js} +4 -4
  26. package/dist/{provider-manager-7C3JVOLW.js → provider-manager-MAKXSL6L.js} +4 -4
  27. package/dist/{pwa-T6JRAYJB.js → pwa-SEWCVKZX.js} +7 -8
  28. package/dist/{serve-NOHD22CT.js → serve-5IOKFKGL.js} +18 -16
  29. package/dist/server/index.js +15 -14
  30. package/dist/{server-RLNPHLY2.js → server-T5QDCUBN.js} +12 -12
  31. package/dist/{service-6DL3MJZD.js → service-2PW2V25M.js} +6 -1
  32. package/dist/{store-FXTCHBI4.js → store-SARB6V2N.js} +2 -2
  33. package/dist/{tools-CALGWIV2.js → tools-K3SNGBI2.js} +14 -14
  34. package/dist/update-734IDLKT.js +40 -0
  35. package/dist/web/assets/{index-CtWMMQ_X.js → index-HTzupfR0.js} +1 -1
  36. package/dist/web/index.html +1 -1
  37. package/dist/web/sw.js +1 -1
  38. package/package.json +2 -2
  39. package/dist/cli/update.sh +0 -16
@@ -1,8 +1,11 @@
1
1
  import {
2
2
  runAgentTurn,
3
3
  runChatTurn
4
- } from "./chunk-UTSSFPYA.js";
5
- import "./chunk-PVWAE43V.js";
4
+ } from "./chunk-X7OCC37J.js";
5
+ import "./chunk-Y4YESMVA.js";
6
+ import "./chunk-VLV3XWZS.js";
7
+ import "./chunk-WGMJCFCE.js";
8
+ import "./chunk-EU3WWTFH.js";
6
9
  import {
7
10
  TurnMetrics,
8
11
  createChatDoneEvent,
@@ -10,26 +13,23 @@ import {
10
13
  createMessageStartEvent,
11
14
  createToolCallEvent,
12
15
  createToolResultEvent
13
- } from "./chunk-QFSDJIUS.js";
16
+ } from "./chunk-RKD2FML3.js";
14
17
  import "./chunk-4QBDV6LX.js";
15
18
  import "./chunk-KXVFHMSM.js";
16
- import "./chunk-TFCHWMOJ.js";
17
- import "./chunk-PK2RMVMB.js";
19
+ import "./chunk-PVUBCGAT.js";
20
+ import "./chunk-I72ACQ6R.js";
18
21
  import "./chunk-NWO6GRYE.js";
19
22
  import "./chunk-UN26GIQG.js";
20
- import "./chunk-VLV3XWZS.js";
21
- import "./chunk-WGMJCFCE.js";
22
23
  import "./chunk-TFDK6VSG.js";
23
24
  import "./chunk-C3VLGVSQ.js";
24
25
  import "./chunk-F4PMNP7S.js";
25
26
  import "./chunk-X5DOUA3Z.js";
26
27
  import "./chunk-XUPKS5FL.js";
27
28
  import "./chunk-GMXKJGJ2.js";
28
- import "./chunk-EU3WWTFH.js";
29
29
  import "./chunk-J2GP3J3X.js";
30
30
  import "./chunk-V4IE7HJY.js";
31
31
  import "./chunk-YHEQTVFV.js";
32
- import "./chunk-JHGKXQBO.js";
32
+ import "./chunk-EZK7CGJ7.js";
33
33
  import "./chunk-K44MW7JJ.js";
34
34
  import "./chunk-YD6NDTKF.js";
35
35
  import "./chunk-WGAAQASA.js";
@@ -45,4 +45,4 @@ export {
45
45
  runAgentTurn,
46
46
  runChatTurn
47
47
  };
48
- //# sourceMappingURL=orchestrator-PUV4WG77.js.map
48
+ //# sourceMappingURL=orchestrator-YGCZZNNV.js.map
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openfox",
3
- "version": "2.0.70",
3
+ "version": "2.0.71",
4
4
  "description": "Local-LLM-first agentic coding assistant",
5
5
  "type": "module",
6
6
  "bin": {
@@ -32,7 +32,7 @@
32
32
  "dev": "OPENFOX_DEV=true tsx watch src/cli/dev.ts --no-browser",
33
33
  "dev:web": "vite --config web/vite.config.ts",
34
34
  "build": "npm run build:server && npm run build:web",
35
- "build:server": "tsup && mkdir -p dist/command-defaults dist/skill-defaults dist/agent-defaults dist/workflow-defaults && cp src/server/commands/defaults/*.md dist/command-defaults/ && cp -r src/server/skills/defaults/* dist/skill-defaults/ && cp src/server/agents/defaults/*.md dist/agent-defaults/ && cp src/server/workflows/defaults/*.json dist/workflow-defaults/ && cp src/server/lsp/languages.json dist/languages.json && cp src/cli/update.sh dist/cli/ && chmod +x dist/cli/update.sh && cp package.json dist/ && cp plugins-registry.json dist/ && cp -r src/server/public dist/server/",
35
+ "build:server": "tsup && mkdir -p dist/command-defaults dist/skill-defaults dist/agent-defaults dist/workflow-defaults && cp src/server/commands/defaults/*.md dist/command-defaults/ && cp -r src/server/skills/defaults/* dist/skill-defaults/ && cp src/server/agents/defaults/*.md dist/agent-defaults/ && cp src/server/workflows/defaults/*.json dist/workflow-defaults/ && cp src/server/lsp/languages.json dist/languages.json && cp package.json dist/ && cp plugins-registry.json dist/ && cp -r src/server/public dist/server/",
36
36
  "build:web": "cd web && vite build --outDir ../dist/web",
37
37
  "start": "node dist/cli/index.js",
38
38
  "start:dev": "node dist/cli/dev.js",
@@ -2,17 +2,18 @@ import {
2
2
  buildRunChatTurnParams,
3
3
  finalizeTurnCompletion,
4
4
  generateSessionNameForSession
5
- } from "./chunk-64GN6OPR.js";
6
- import "./chunk-PVWAE43V.js";
7
- import "./chunk-QFSDJIUS.js";
5
+ } from "./chunk-NEL2REUM.js";
6
+ import "./chunk-Y4YESMVA.js";
7
+ import "./chunk-VLV3XWZS.js";
8
+ import "./chunk-WGMJCFCE.js";
9
+ import "./chunk-EU3WWTFH.js";
10
+ import "./chunk-RKD2FML3.js";
8
11
  import "./chunk-4QBDV6LX.js";
9
12
  import "./chunk-KXVFHMSM.js";
10
- import "./chunk-TFCHWMOJ.js";
11
- import "./chunk-PK2RMVMB.js";
13
+ import "./chunk-PVUBCGAT.js";
14
+ import "./chunk-I72ACQ6R.js";
12
15
  import "./chunk-NWO6GRYE.js";
13
16
  import "./chunk-UN26GIQG.js";
14
- import "./chunk-VLV3XWZS.js";
15
- import "./chunk-WGMJCFCE.js";
16
17
  import {
17
18
  getEventStore
18
19
  } from "./chunk-TFDK6VSG.js";
@@ -24,11 +25,10 @@ import {
24
25
  import "./chunk-X5DOUA3Z.js";
25
26
  import "./chunk-XUPKS5FL.js";
26
27
  import "./chunk-GMXKJGJ2.js";
27
- import "./chunk-EU3WWTFH.js";
28
28
  import "./chunk-J2GP3J3X.js";
29
29
  import "./chunk-V4IE7HJY.js";
30
30
  import "./chunk-YHEQTVFV.js";
31
- import "./chunk-JHGKXQBO.js";
31
+ import "./chunk-EZK7CGJ7.js";
32
32
  import {
33
33
  logger
34
34
  } from "./chunk-K44MW7JJ.js";
@@ -179,7 +179,7 @@ var QueueProcessor = class {
179
179
  backend: provider?.backend ?? llmClient.getBackend(),
180
180
  model: llmClient.getModel()
181
181
  };
182
- const { runChatTurn } = await import("./orchestrator-PUV4WG77.js");
182
+ const { runChatTurn } = await import("./orchestrator-YGCZZNNV.js");
183
183
  const runChatTurnParams = buildRunChatTurnParams({
184
184
  sessionManager,
185
185
  sessionId,
@@ -227,4 +227,4 @@ var QueueProcessor = class {
227
227
  export {
228
228
  QueueProcessor
229
229
  };
230
- //# sourceMappingURL=processor-O2QW27BD.js.map
230
+ //# sourceMappingURL=processor-K6UPVMIP.js.map
@@ -11,13 +11,13 @@ import {
11
11
  import {
12
12
  detectModel,
13
13
  fetchAvailableModelsFromBackend
14
- } from "./chunk-7OW6X764.js";
14
+ } from "./chunk-OHGQILRF.js";
15
15
  import "./chunk-J2GP3J3X.js";
16
- import "./chunk-E4POUD2M.js";
16
+ import "./chunk-6XOA2WPU.js";
17
17
  import "./chunk-V4IE7HJY.js";
18
18
  import "./chunk-YHEQTVFV.js";
19
19
  import "./chunk-HNCM3D7Y.js";
20
- import "./chunk-JHGKXQBO.js";
20
+ import "./chunk-EZK7CGJ7.js";
21
21
  import "./chunk-ZO5EXQMG.js";
22
22
  import "./chunk-K44MW7JJ.js";
23
23
  import {
@@ -396,4 +396,4 @@ export {
396
396
  runProviderRemove,
397
397
  runProviderUse
398
398
  };
399
- //# sourceMappingURL=provider-IBIWR4AI.js.map
399
+ //# sourceMappingURL=provider-OJUCZ5RN.js.map
@@ -3,13 +3,13 @@ import {
3
3
  fetchAvailableModelsFromBackend,
4
4
  fetchModelsWithContext,
5
5
  parseDefaultModelSelection
6
- } from "./chunk-7OW6X764.js";
6
+ } from "./chunk-OHGQILRF.js";
7
7
  import "./chunk-J2GP3J3X.js";
8
- import "./chunk-E4POUD2M.js";
8
+ import "./chunk-6XOA2WPU.js";
9
9
  import "./chunk-V4IE7HJY.js";
10
10
  import "./chunk-YHEQTVFV.js";
11
11
  import "./chunk-HNCM3D7Y.js";
12
- import "./chunk-JHGKXQBO.js";
12
+ import "./chunk-EZK7CGJ7.js";
13
13
  import "./chunk-ZO5EXQMG.js";
14
14
  import "./chunk-K44MW7JJ.js";
15
15
  import "./chunk-5WRI5ZAA.js";
@@ -19,4 +19,4 @@ export {
19
19
  fetchModelsWithContext,
20
20
  parseDefaultModelSelection
21
21
  };
22
- //# sourceMappingURL=provider-manager-7C3JVOLW.js.map
22
+ //# sourceMappingURL=provider-manager-MAKXSL6L.js.map
@@ -106,14 +106,12 @@ function probeInstalledApp(manifestUrl) {
106
106
  }
107
107
  return null;
108
108
  }
109
- function isServerReachable(port) {
109
+ async function isServerReachable(port) {
110
110
  try {
111
- const result = execSync(`curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:${port}/manifest.webmanifest`, {
112
- encoding: "utf-8",
113
- timeout: 5e3,
114
- windowsHide: true
111
+ const res = await fetch(`http://127.0.0.1:${port}/manifest.webmanifest`, {
112
+ signal: AbortSignal.timeout(5e3)
115
113
  });
116
- return result.trim() === "200";
114
+ return res.ok;
117
115
  } catch {
118
116
  return false;
119
117
  }
@@ -191,7 +189,7 @@ See: https://pwasforfirefox.filips.si/installation/`);
191
189
  }
192
190
  }
193
191
  const port = mode === "development" ? 10469 : 10369;
194
- if (!isServerReachable(port)) {
192
+ if (!await isServerReachable(port)) {
195
193
  R.error(`OpenFox server is not reachable on port ${port}.`);
196
194
  console.log(`
197
195
  Start OpenFox first:
@@ -355,10 +353,11 @@ Run: firefoxpwa runtime install`);
355
353
  }
356
354
  export {
357
355
  getManifestUrl,
356
+ isServerReachable,
358
357
  loadPwaConfig,
359
358
  printPwaHelp,
360
359
  removePwaConfig,
361
360
  runPwaCommand,
362
361
  savePwaConfig
363
362
  };
364
- //# sourceMappingURL=pwa-T6JRAYJB.js.map
363
+ //# sourceMappingURL=pwa-SEWCVKZX.js.map
@@ -1,20 +1,23 @@
1
1
  import {
2
- VERSION,
3
2
  createServer
4
- } from "./chunk-ZZ5JPVBT.js";
5
- import "./chunk-46OR4W3L.js";
6
- import "./chunk-UTSSFPYA.js";
7
- import "./chunk-PVWAE43V.js";
8
- import "./chunk-YQ3MEZJL.js";
9
- import "./chunk-QFSDJIUS.js";
3
+ } from "./chunk-OLXHRPAD.js";
4
+ import "./chunk-Z42YTK3O.js";
5
+ import "./chunk-X7OCC37J.js";
6
+ import "./chunk-Y4YESMVA.js";
7
+ import "./chunk-VLV3XWZS.js";
8
+ import "./chunk-WGMJCFCE.js";
9
+ import "./chunk-EU3WWTFH.js";
10
+ import "./chunk-TQGGMWS6.js";
11
+ import "./chunk-RKD2FML3.js";
10
12
  import "./chunk-4QBDV6LX.js";
11
13
  import "./chunk-KXVFHMSM.js";
12
- import "./chunk-TFCHWMOJ.js";
13
- import "./chunk-PK2RMVMB.js";
14
+ import "./chunk-PVUBCGAT.js";
15
+ import "./chunk-I72ACQ6R.js";
14
16
  import "./chunk-NWO6GRYE.js";
15
17
  import "./chunk-UN26GIQG.js";
16
- import "./chunk-VLV3XWZS.js";
17
- import "./chunk-WGMJCFCE.js";
18
+ import {
19
+ VERSION
20
+ } from "./chunk-7NMOWPNY.js";
18
21
  import {
19
22
  loadConfig
20
23
  } from "./chunk-TFDK6VSG.js";
@@ -23,14 +26,13 @@ import "./chunk-F4PMNP7S.js";
23
26
  import "./chunk-X5DOUA3Z.js";
24
27
  import "./chunk-XUPKS5FL.js";
25
28
  import "./chunk-GMXKJGJ2.js";
26
- import "./chunk-EU3WWTFH.js";
27
- import "./chunk-7OW6X764.js";
29
+ import "./chunk-OHGQILRF.js";
28
30
  import "./chunk-J2GP3J3X.js";
29
- import "./chunk-E4POUD2M.js";
31
+ import "./chunk-6XOA2WPU.js";
30
32
  import "./chunk-V4IE7HJY.js";
31
33
  import "./chunk-YHEQTVFV.js";
32
34
  import "./chunk-HNCM3D7Y.js";
33
- import "./chunk-JHGKXQBO.js";
35
+ import "./chunk-EZK7CGJ7.js";
34
36
  import "./chunk-ZO5EXQMG.js";
35
37
  import {
36
38
  logger
@@ -208,4 +210,4 @@ async function runServe(options) {
208
210
  export {
209
211
  runServe
210
212
  };
211
- //# sourceMappingURL=serve-NOHD22CT.js.map
213
+ //# sourceMappingURL=serve-5IOKFKGL.js.map
@@ -1,34 +1,35 @@
1
1
  import {
2
2
  createServer,
3
3
  createServerHandle
4
- } from "../chunk-ZZ5JPVBT.js";
5
- import "../chunk-46OR4W3L.js";
6
- import "../chunk-UTSSFPYA.js";
7
- import "../chunk-PVWAE43V.js";
8
- import "../chunk-YQ3MEZJL.js";
9
- import "../chunk-QFSDJIUS.js";
4
+ } from "../chunk-OLXHRPAD.js";
5
+ import "../chunk-Z42YTK3O.js";
6
+ import "../chunk-X7OCC37J.js";
7
+ import "../chunk-Y4YESMVA.js";
8
+ import "../chunk-VLV3XWZS.js";
9
+ import "../chunk-WGMJCFCE.js";
10
+ import "../chunk-EU3WWTFH.js";
11
+ import "../chunk-TQGGMWS6.js";
12
+ import "../chunk-RKD2FML3.js";
10
13
  import "../chunk-4QBDV6LX.js";
11
14
  import "../chunk-KXVFHMSM.js";
12
- import "../chunk-TFCHWMOJ.js";
13
- import "../chunk-PK2RMVMB.js";
15
+ import "../chunk-PVUBCGAT.js";
16
+ import "../chunk-I72ACQ6R.js";
14
17
  import "../chunk-NWO6GRYE.js";
15
18
  import "../chunk-UN26GIQG.js";
16
- import "../chunk-VLV3XWZS.js";
17
- import "../chunk-WGMJCFCE.js";
19
+ import "../chunk-7NMOWPNY.js";
18
20
  import "../chunk-TFDK6VSG.js";
19
21
  import "../chunk-C3VLGVSQ.js";
20
22
  import "../chunk-F4PMNP7S.js";
21
23
  import "../chunk-X5DOUA3Z.js";
22
24
  import "../chunk-XUPKS5FL.js";
23
25
  import "../chunk-GMXKJGJ2.js";
24
- import "../chunk-EU3WWTFH.js";
25
- import "../chunk-7OW6X764.js";
26
+ import "../chunk-OHGQILRF.js";
26
27
  import "../chunk-J2GP3J3X.js";
27
- import "../chunk-E4POUD2M.js";
28
+ import "../chunk-6XOA2WPU.js";
28
29
  import "../chunk-V4IE7HJY.js";
29
30
  import "../chunk-YHEQTVFV.js";
30
31
  import "../chunk-HNCM3D7Y.js";
31
- import "../chunk-JHGKXQBO.js";
32
+ import "../chunk-EZK7CGJ7.js";
32
33
  import "../chunk-ZO5EXQMG.js";
33
34
  import "../chunk-K44MW7JJ.js";
34
35
  import "../chunk-VUQCQXXJ.js";
@@ -1,30 +1,30 @@
1
1
  import {
2
2
  createWebSocketServer,
3
3
  signalMcpReady
4
- } from "./chunk-46OR4W3L.js";
5
- import "./chunk-UTSSFPYA.js";
6
- import "./chunk-PVWAE43V.js";
7
- import "./chunk-YQ3MEZJL.js";
8
- import "./chunk-QFSDJIUS.js";
4
+ } from "./chunk-Z42YTK3O.js";
5
+ import "./chunk-X7OCC37J.js";
6
+ import "./chunk-Y4YESMVA.js";
7
+ import "./chunk-VLV3XWZS.js";
8
+ import "./chunk-WGMJCFCE.js";
9
+ import "./chunk-EU3WWTFH.js";
10
+ import "./chunk-TQGGMWS6.js";
11
+ import "./chunk-RKD2FML3.js";
9
12
  import "./chunk-4QBDV6LX.js";
10
13
  import "./chunk-KXVFHMSM.js";
11
- import "./chunk-TFCHWMOJ.js";
12
- import "./chunk-PK2RMVMB.js";
14
+ import "./chunk-PVUBCGAT.js";
15
+ import "./chunk-I72ACQ6R.js";
13
16
  import "./chunk-NWO6GRYE.js";
14
17
  import "./chunk-UN26GIQG.js";
15
- import "./chunk-VLV3XWZS.js";
16
- import "./chunk-WGMJCFCE.js";
17
18
  import "./chunk-TFDK6VSG.js";
18
19
  import "./chunk-C3VLGVSQ.js";
19
20
  import "./chunk-F4PMNP7S.js";
20
21
  import "./chunk-X5DOUA3Z.js";
21
22
  import "./chunk-XUPKS5FL.js";
22
23
  import "./chunk-GMXKJGJ2.js";
23
- import "./chunk-EU3WWTFH.js";
24
24
  import "./chunk-J2GP3J3X.js";
25
25
  import "./chunk-V4IE7HJY.js";
26
26
  import "./chunk-YHEQTVFV.js";
27
- import "./chunk-JHGKXQBO.js";
27
+ import "./chunk-EZK7CGJ7.js";
28
28
  import "./chunk-K44MW7JJ.js";
29
29
  import "./chunk-VUQCQXXJ.js";
30
30
  import "./chunk-YD6NDTKF.js";
@@ -35,4 +35,4 @@ export {
35
35
  createWebSocketServer,
36
36
  signalMcpReady
37
37
  };
38
- //# sourceMappingURL=server-RLNPHLY2.js.map
38
+ //# sourceMappingURL=server-T5QDCUBN.js.map
@@ -126,6 +126,11 @@ WantedBy=graphical-session.target
126
126
  console.log(`Created: ${servicePath}`);
127
127
  }
128
128
  async function runServiceCommand(_mode, subcommand, ...args) {
129
+ if (process.platform === "win32") {
130
+ console.log("openfox service is not supported on Windows (it relies on systemd). Run `openfox` directly instead.");
131
+ process.exitCode = 1;
132
+ return;
133
+ }
129
134
  if (!subcommand) {
130
135
  printServiceHelp();
131
136
  return;
@@ -291,4 +296,4 @@ async function serviceUninstall() {
291
296
  export {
292
297
  runServiceCommand
293
298
  };
294
- //# sourceMappingURL=service-6DL3MJZD.js.map
299
+ //# sourceMappingURL=service-2PW2V25M.js.map
@@ -13,7 +13,7 @@ import {
13
13
  removeProcess,
14
14
  startProcess,
15
15
  updateStatus
16
- } from "./chunk-PK2RMVMB.js";
16
+ } from "./chunk-I72ACQ6R.js";
17
17
  import "./chunk-5WRI5ZAA.js";
18
18
  export {
19
19
  appendLog,
@@ -31,4 +31,4 @@ export {
31
31
  startProcess,
32
32
  updateStatus
33
33
  };
34
- //# sourceMappingURL=store-FXTCHBI4.js.map
34
+ //# sourceMappingURL=store-SARB6V2N.js.map
@@ -12,32 +12,32 @@ import {
12
12
  setMcpTools,
13
13
  stepDoneTool,
14
14
  validateToolAction
15
- } from "./chunk-PVWAE43V.js";
16
- import "./chunk-QFSDJIUS.js";
15
+ } from "./chunk-Y4YESMVA.js";
16
+ import "./chunk-VLV3XWZS.js";
17
+ import "./chunk-WGMJCFCE.js";
18
+ import {
19
+ AskUserInterrupt,
20
+ cancelQuestionsForSession,
21
+ getPendingQuestionsForSession,
22
+ provideAnswer
23
+ } from "./chunk-EU3WWTFH.js";
24
+ import "./chunk-RKD2FML3.js";
17
25
  import "./chunk-4QBDV6LX.js";
18
26
  import "./chunk-KXVFHMSM.js";
19
- import "./chunk-TFCHWMOJ.js";
20
- import "./chunk-PK2RMVMB.js";
27
+ import "./chunk-PVUBCGAT.js";
28
+ import "./chunk-I72ACQ6R.js";
21
29
  import "./chunk-NWO6GRYE.js";
22
30
  import "./chunk-UN26GIQG.js";
23
- import "./chunk-VLV3XWZS.js";
24
- import "./chunk-WGMJCFCE.js";
25
31
  import "./chunk-TFDK6VSG.js";
26
32
  import "./chunk-C3VLGVSQ.js";
27
33
  import "./chunk-F4PMNP7S.js";
28
34
  import "./chunk-X5DOUA3Z.js";
29
35
  import "./chunk-XUPKS5FL.js";
30
36
  import "./chunk-GMXKJGJ2.js";
31
- import {
32
- AskUserInterrupt,
33
- cancelQuestionsForSession,
34
- getPendingQuestionsForSession,
35
- provideAnswer
36
- } from "./chunk-EU3WWTFH.js";
37
37
  import "./chunk-J2GP3J3X.js";
38
38
  import "./chunk-V4IE7HJY.js";
39
39
  import "./chunk-YHEQTVFV.js";
40
- import "./chunk-JHGKXQBO.js";
40
+ import "./chunk-EZK7CGJ7.js";
41
41
  import "./chunk-K44MW7JJ.js";
42
42
  import "./chunk-YD6NDTKF.js";
43
43
  import "./chunk-WGAAQASA.js";
@@ -62,4 +62,4 @@ export {
62
62
  stepDoneTool,
63
63
  validateToolAction
64
64
  };
65
- //# sourceMappingURL=tools-CALGWIV2.js.map
65
+ //# sourceMappingURL=tools-K3SNGBI2.js.map
@@ -0,0 +1,40 @@
1
+ import {
2
+ VERSION
3
+ } from "./chunk-7NMOWPNY.js";
4
+ import "./chunk-5WRI5ZAA.js";
5
+
6
+ // src/cli/update.ts
7
+ import { spawnSync } from "child_process";
8
+ function npm(args, inherit = false) {
9
+ const win = process.platform === "win32";
10
+ const result = spawnSync(win ? ["npm", ...args].join(" ") : "npm", win ? [] : args, {
11
+ encoding: "utf-8",
12
+ ...inherit ? { stdio: "inherit" } : {},
13
+ shell: win,
14
+ windowsHide: true
15
+ });
16
+ return { ok: result.status === 0, stdout: (result.stdout ?? "").trim() };
17
+ }
18
+ function runUpdate() {
19
+ const view = npm(["view", "openfox", "version"]);
20
+ if (!view.ok) {
21
+ console.error("Failed to check the latest version (npm view openfox version)");
22
+ return 1;
23
+ }
24
+ const latest = view.stdout;
25
+ if (VERSION === latest) {
26
+ console.log(`OpenFox is already at the latest version: ${VERSION}`);
27
+ return 0;
28
+ }
29
+ console.log(`Updating OpenFox: ${VERSION} -> ${latest}`);
30
+ if (!npm(["install", "-g", "openfox@latest"], true).ok) {
31
+ return 1;
32
+ }
33
+ console.log(`Updated: ${latest}`);
34
+ console.log("Please restart OpenFox to use the new version.");
35
+ return 0;
36
+ }
37
+ export {
38
+ runUpdate
39
+ };
40
+ //# sourceMappingURL=update-734IDLKT.js.map
@@ -302,4 +302,4 @@ XID_Start XIDS`.split(/\s/).map(e=>[Nd(e),e])),E6=new Map([["s",mn(383)],[mn(383
302
302
 
303
303
  ${oe}`:oe;(re=d.current)==null||re.scrollTo({top:d.current.scrollHeight,behavior:"smooth"}),J(yt,Xe!=null&&Xe.length?Xe:void 0,{messageKind:"command",isSystemGenerated:!0}),P()},onSelectWorkflow:L,onSelectWorkflowWithSubGroup:O,onOpenCommandsManager:T,onOpenWorkflowsManager:R,onAttach:Ae,textareaContent:e,attachments:n.length>0?n:void 0})]})]})]}),i.jsxs("div",{className:"mt-3 flex items-center justify-between",children:[i.jsxs("div",{className:"flex items-center gap-2",children:[i.jsx(_$,{}),i.jsx(v$,{})]}),i.jsx(k$,{})]})]})}function T$(e){return(e.ctrlKey||e.metaKey)&&e.key.toLowerCase()==="f"&&document.querySelector("[data-global-settings]")===null}function Tk(e,t=[]){const n=[];let r=null,o,l=1;const u=new Map,c=new Map;for(const f of t)f.type==="message"?u.set(f.message.id,f):f.type==="subagent"&&c.set(f.subAgentId,f);const d=()=>{if(!r)return;const f=r,p=c.get(f.subAgentId);p&&p.type==="subagent"&&p.messages.length===f.messages.length&&p.messages.every((x,y)=>x===f.messages[y])?n.push(p):n.push({type:"subagent",subAgentId:f.subAgentId,subAgentType:f.subAgentType,messages:f.messages}),r=null};for(const f of e)if(f.role!=="tool")if(f.contextWindowId&&o&&f.contextWindowId!==o&&(d(),l++,n.push({type:"context-divider",windowSequence:l})),o=f.contextWindowId,f.subAgentId&&f.subAgentType)r&&r.subAgentId===f.subAgentId?r.messages.push(f):(d(),r={subAgentId:f.subAgentId,subAgentType:f.subAgentType,messages:[f]});else{d();const p=u.get(f.id);p&&p.type==="message"&&p.message===f?n.push(p):n.push({type:"message",message:f})}return d(),n}function A$(e){const{year:t,month:n,day:r}=v1(e);return`${t}/${n}/${r} ${cd(e)}`}function L$(e,t){return e.length<=t?e:e.substring(0,t)+"..."}const R$=10,D$=150;function O$(e){const t=[];if(e.recentUserPrompts)for(const n of e.recentUserPrompts)t.push({id:n.id,content:n.content,timestamp:n.timestamp,sessionId:e.id,sessionName:e.title||e.id});return t}function I$(e){return[...e].sort((r,o)=>new Date(o.timestamp).getTime()-new Date(r.timestamp).getTime()).slice(0,R$).reverse().map(r=>({id:r.id,content:r.content,timestamp:r.timestamp,formattedTimestamp:A$(r.timestamp),trimmedContent:L$(r.content,D$),sessionId:r.sessionId,sessionName:r.sessionName}))}function M$(e,t,n){const r=[],o=e.filter(l=>l.role==="user"&&!l.isSystemGenerated&&l.messageKind!=="auto-prompt");for(const l of o)r.push({id:l.id,content:l.content,timestamp:l.timestamp,sessionId:n??"",sessionName:"This session"});for(const l of t)n&&l.id===n||r.push(...O$(l));return I$(r)}function P$(e,t=[],n=null){const[r,o]=A.useState(0),[l,u]=A.useState(!1),c=A.useMemo(()=>M$(e,t,n),[e,t,n]),d=A.useCallback(()=>{c.length>0&&(o(c.length-1),u(!0))},[c.length]),f=A.useCallback(()=>{u(!1),o(0)},[]),p=A.useCallback(()=>{o(y=>c.length===0?y:y===0?c.length-1:y-1)},[c.length]),m=A.useCallback(()=>{o(y=>c.length===0?y:y===c.length-1?0:y+1)},[c.length]),x=A.useCallback(()=>{if(c.length===0||!l)return null;const y=c[r];return(y==null?void 0:y.content)??null},[c,r,l]);return{history:c,selectedIndex:r,showHistory:l,openHistory:d,closeHistory:f,navigateUp:p,navigateDown:m,selectCurrent:x}}A.memo(function({item:t}){const[n,r]=A.useState(!1);return t.type==="start"?i.jsxs("div",{className:"flex items-center gap-2 px-3 py-2 bg-amber-500/10 border border-amber-500/30 rounded text-amber-300 text-sm",children:[i.jsx("span",{className:"animate-pulse",children:"●"}),i.jsx("span",{children:"Delegating image to fallback vision model..."}),t.filename&&i.jsxs("span",{className:"text-amber-400/70",children:["(",t.filename,")"]})]}):i.jsxs("div",{className:"flex items-start gap-2 px-3 py-2 bg-accent-success/10 border border-accent-success/30 rounded",children:[i.jsx("span",{className:"text-accent-success",children:"✓"}),i.jsxs("div",{className:"flex-1 min-w-0",children:[i.jsxs("div",{className:"flex items-center justify-between gap-2",children:[i.jsx("span",{className:"text-accent-success text-sm",children:"Image description done"}),i.jsx("button",{type:"button",onClick:()=>r(!n),className:"text-xs text-accent-primary hover:text-accent-primary/80 transition-colors",children:n?"Hide":"Show"})]}),n&&t.description&&i.jsx("div",{className:"mt-2 text-xs prose prose-invert prose-sm max-w-none",children:i.jsx(Vn,{content:t.description})})]})]})});function B$({criteriaSidebarOpen:e,onCriteriaSidebarToggle:t}={}){const n=e??!0,[r,o]=A.useState(""),[l,u]=A.useState([]),[c,d]=A.useState(!1),[f,p]=A.useState(null),[m,x]=A.useState(!1),[y,w]=A.useState(!1),[C,v]=A.useState(!1),[S,_]=A.useState(!1),[b,j]=A.useState(null),E=A.useRef(null),T=Re(Ne=>Ne.currentSession),R=Re(Ne=>Ne.messages),L=Re(Ne=>Ne.sessions),O=id(),P=Re(Ne=>Ne.stopGeneration),G=kt(Ne=>Ne.defaults),W=kt(Ne=>Ne.userItems),I=[...G,...W].filter(Ne=>!Ne.subagent),{history:H,selectedIndex:V,showHistory:U,openHistory:Q,closeHistory:X,navigateUp:z,navigateDown:D,selectCurrent:B}=P$(R,L,T==null?void 0:T.id);A.useEffect(()=>{const Ne=Te=>{j(Te.detail.stats)};return window.addEventListener("open-turn-stats",Ne),()=>window.removeEventListener("open-turn-stats",Ne)},[]),A.useEffect(()=>{Ot.getState().fetchWorkflows()},[]),A.useEffect(()=>{const Ne=Te=>{T$(Te)&&(Te.preventDefault(),_(!0))};return window.addEventListener("keydown",Ne),()=>window.removeEventListener("keydown",Ne)},[]);const{maxVisibleItems:q}=zi(),M=A.useRef([]),{displayItems:ee,hiddenCount:J}=A.useMemo(()=>{const Ne=Tk(R,M.current);return M.current=Ne,q>0&&Ne.length>q?{displayItems:Ne.slice(-q),hiddenCount:Ne.length-q}:{displayItems:Ne,hiddenCount:0}},[R,q]),{isAutoScrollActive:ne,setAutoScroll:K}=dd(E,T),{sendMessage:F,launchWorkflow:te}=Ek(K),se=A.useCallback((Ne,Te)=>{te(void 0,void 0,Ne,Te)},[te]),me=A.useCallback(Ne=>{var We;K(!1);const Te=document.querySelector(`[data-item-index="${Ne}"]`);Te&&(Te.scrollIntoView({behavior:"smooth",block:"start"}),(We=Te.closest('[data-testid="chat-scroll-container"]'))==null||We.scrollBy(0,-80))},[K]);A.useEffect(()=>{const Ne=Te=>{const We=C||m||y||S||b;Te.key==="Escape"&&O&&!We&&P(),Te.key==="ScrollLock"&&K(!ne)};return window.addEventListener("keydown",Ne),()=>window.removeEventListener("keydown",Ne)},[O,P,ne,C,m,y,S,b]);const be=Bp();r1(be.quickAction,()=>{v(!0)}),LN(be.agentSwitching,I,Ne=>{Re.getState().switchMode(Ne)});const ze=Ne=>{const Te=r.trim()?r:void 0,We=l.length>0?l:void 0;te(Te,We,Ne),Ae()},$e=(Ne,Te)=>{const We=r.trim()?r:void 0,Ee=l.length>0?l:void 0;te(We,Ee,Ne,Te),Ae()},Ae=()=>{o(""),u([]),T!=null&&T.id&&localStorage.removeItem(`openfox:draft:${T.id}`)};return i.jsxs(i.Fragment,{children:[i.jsxs(wA,{criteriaSidebarOpen:n,onCriteriaSidebarToggle:t,messages:R,children:[i.jsx(EA,{}),b&&i.jsx(jA,{stats:b,onClose:()=>j(null)}),i.jsx(k8,{}),i.jsx(w8,{displayItems:ee,scrollContainerRef:E,highlightedMessageId:null,onLaunchWorkflow:se,hiddenCount:J}),i.jsx(N$,{input:r,setInput:o,attachments:l,setAttachments:u,dragOver:c,setDragOver:d,errorMessage:f,setErrorMessage:p,scrollContainerRef:E,sessionId:T==null?void 0:T.id,sessionMode:T==null?void 0:T.mode,showHistory:U,history:H,selectedIndex:V,openHistory:Q,closeHistory:X,navigateUp:z,navigateDown:D,selectCurrent:B,isAutoScrollActive:ne,setAutoScroll:K,onOpenMessageSearch:()=>_(!0),onOpenCommandsModal:()=>x(!0),onOpenWorkflowsModal:()=>w(!0),onSelectWorkflow:ze,onSelectWorkflowWithSubGroup:$e,clearInput:Ae}),i.jsx(_k,{isOpen:m,onClose:()=>x(!1)}),i.jsx(wk,{isOpen:y,onClose:()=>w(!1)}),i.jsx(B8,{isOpen:C,onClose:()=>v(!1),onSearchMessages:()=>_(!0),isAutoScrollActive:ne,onToggleAutoScroll:K,textareaContent:r,onCloseComplete:Jm,onCloseCompleteAction:()=>window.dispatchEvent(new CustomEvent("open-session-dropdown")),onSelectCommand:async(Ne,Te)=>{const We=await dn.getState().fetchCommand(Ne);if(We){const Ee=Te!=null&&Te.trim()?`${Te.trim()}
304
304
 
305
- ${We.prompt}`:We.prompt;We.metadata.agentMode&&Re.getState().switchMode(We.metadata.agentMode),F(Ee,l!=null&&l.length?l:void 0,{messageKind:"command",isSystemGenerated:!0}),Ae()}},onSelectWorkflow:Ne=>{const Te=r.trim()||void 0,We=l.length>0?l:void 0;te(Te,We,Ne),Ae()}})]}),S&&i.jsx(q8,{isOpen:S,onClose:()=>{_(!1),Jm()},displayItems:ee,onNavigate:me})]})}function $$(){var S;const[,e]=Xa("/p/:projectId/s/:sessionId/readonly"),t=e==null?void 0:e.sessionId,[n,r]=A.useState(null),[o,l]=A.useState([]),[u,c]=A.useState(!0),[d,f]=A.useState(null),p=async()=>{if(t){c(!0),f(null);try{const _=await Se(`/api/sessions/${t}`);if(!_.ok){f(`Failed to load session (${_.status})`),c(!1);return}const b=await _.json();r(b.session??null),l(b.messages??[])}catch(_){f(_ instanceof Error?_.message:"Unknown error")}finally{c(!1)}}};A.useEffect(()=>{tn.getState().getSettings([...Lp])},[]),A.useEffect(()=>{p()},[t]);const{showThinking:m,showVerboseToolOutput:x,showStats:y,showAgentDefinitions:w,showWorkflowBars:C}=zi(),v=A.useMemo(()=>Tk(o),[o]);return u?i.jsx("div",{className:"h-screen flex items-center justify-center bg-primary",children:i.jsx(ri,{})}):d?i.jsx("div",{className:"h-screen flex items-center justify-center bg-primary",children:i.jsxs("div",{className:"text-center space-y-4",children:[i.jsx("div",{className:"text-red-400 text-sm",children:d}),i.jsx("button",{onClick:p,className:"px-3 py-1.5 text-sm bg-bg-tertiary text-text-primary border border-border rounded hover:bg-bg-tertiary/80 transition-colors",children:"Retry"})]})}):i.jsxs("div",{className:"h-screen print:h-auto flex flex-col bg-primary",children:[i.jsxs("div",{className:"flex items-center justify-between px-4 py-2 border-b border-border bg-secondary shrink-0 print:hidden",children:[i.jsxs("div",{className:"flex items-center gap-3 min-w-0",children:[i.jsxs("h1",{className:"text-sm font-medium text-text-primary truncate",children:[((S=n==null?void 0:n.metadata)==null?void 0:S.title)??"Session"," — Read-only view"]}),i.jsxs("span",{className:"text-xs text-text-muted whitespace-nowrap",children:[o.length," messages"]})]}),i.jsx("div",{className:"flex items-center gap-2",children:i.jsx("button",{onClick:p,disabled:u,className:"px-3 py-1 text-xs bg-bg-tertiary text-text-primary border border-border rounded hover:bg-bg-tertiary/80 transition-colors disabled:opacity-50",children:u?"Refreshing...":"Refresh"})})]}),i.jsxs("div",{className:"flex-1 overflow-y-auto print:overflow-visible",children:[i.jsx("div",{className:"pt-4",children:i.jsx(yk,{displayItems:v,showThinking:m,showVerboseToolOutput:x,showStats:y,showAgentDefinitions:w,showWorkflowBars:C})}),i.jsx("div",{className:"h-8"})]})]})}function TS({isOpen:e,isRetry:t,onSubmit:n,onCancel:r}){const[o,l]=A.useState(""),u=A.useRef(null);A.useEffect(()=>{e&&(l(""),setTimeout(()=>{var d;return(d=u.current)==null?void 0:d.focus()},100))},[e]);const c=d=>{d.preventDefault(),o.trim()&&n(o)};return i.jsx(At,{isOpen:e,onClose:r,title:t?"Invalid Password":"Password Required",size:"sm",children:i.jsxs("form",{onSubmit:c,className:"space-y-4",children:[i.jsx("p",{className:"text-text-secondary text-sm",children:t?"The password you entered was incorrect. Please try again.":"This server requires a password to connect."}),i.jsx(Mi,{ref:u,type:"password",value:o,onChange:d=>l(d.target.value),placeholder:"Enter password",autoFocus:!0}),i.jsxs("div",{className:"flex justify-end gap-2",children:[i.jsx(tt,{type:"button",variant:"secondary",onClick:r,children:"Cancel"}),i.jsx(tt,{type:"submit",disabled:!o.trim(),children:t?"Try Again":"Connect"})]})]})})}function z$({currentStep:e,totalSteps:t,labels:n,onStepClick:r}){return i.jsx("div",{className:"flex justify-center py-6",children:i.jsx("div",{className:"flex items-center",children:Array.from({length:t},(o,l)=>{const u=l+1,c=u<e,d=u===e;return i.jsxs("div",{className:"flex items-center",children:[i.jsx("button",{onClick:()=>r==null?void 0:r(u),className:`size-8 rounded-full flex items-center justify-center text-sm font-medium transition-colors shrink-0 ${c?"bg-accent-primary text-text-primary hover:opacity-80":d?"bg-accent-primary text-text-primary":"bg-bg-tertiary text-text-muted"}`,children:c?"✓":u}),i.jsx("button",{onClick:()=>r==null?void 0:r(u),className:`ml-2 mr-4 text-sm whitespace-nowrap hidden sm:block ${d?"text-text-primary font-medium":"text-text-muted hover:text-text-secondary"}`,children:n[l]}),l<t-1&&i.jsx("div",{className:`w-12 sm:w-20 h-0.5 mr-4 ${c?"bg-accent-primary":"bg-border"}`})]},l)})})})}function H$({onNext:e}){const[t,n]=A.useState([]),[r,o]=A.useState([]),[l,u]=A.useState(!1),[c,d]=A.useState(null),[f,p]=A.useState(null),[m,x]=A.useState(null);A.useEffect(()=>{y()},[]);async function y(){try{const E=await Se("/api/providers");if(E.ok){const R=(await E.json()).providers.map(L=>({id:L.id,name:L.name,url:L.url,backend:L.backend,model:null,apiKey:L.apiKey,isLocal:L.isLocal,thinkingField:L.thinkingField,models:L.models}));n(R),o(R)}}catch{}}async function w(E){const T=E.id.startsWith("temp-"),R=r.some(P=>P.id===E.id),L=r.length===0&&c===null,O=jk(E);try{let P;if(T){const W=await Se("/api/providers",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(O)});if(!W.ok)throw new Error("Failed to create provider");const I=await W.json();P={...E,id:I.provider.id,model:null}}else{if(!(await Se(`/api/providers/${E.id}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(O)})).ok)throw new Error("Failed to update provider");P={...E,model:null}}const G=W=>W.some(I=>I.id===P.id)?W.map(I=>I.id===P.id?P:I):[...W,P];o(G),n(G),L&&!R&&e({providers:[P]})}catch{if(T){const P={...E,model:null};o(G=>[...G,P])}}}function C(){d(null),u(!0)}function v(E){d(E),u(!0)}function S(){u(!1),d(null)}function _(E){p(E),t.some(R=>R.id===E)?Se(`/api/providers/${E}`,{method:"DELETE"}).then(()=>{o(r.filter(R=>R.id!==E)),n(t.filter(R=>R.id!==E)),p(null)}).catch(()=>p(null)):(o(r.filter(R=>R.id!==E)),p(null))}function b(){const E=r.filter(T=>!T.id.startsWith("temp-"));e({providers:E})}const j=r.length>0;return i.jsxs("div",{className:"max-w-xl mx-auto",children:[i.jsx("h2",{className:"text-2xl font-bold text-text-primary mb-2",children:"LLM Providers"}),i.jsx("p",{className:"text-text-secondary mb-8",children:"Manage your LLM server connections"}),i.jsxs("div",{className:"space-y-4",children:[r.length>0?i.jsx("div",{className:"space-y-2",children:r.map(E=>i.jsxs("div",{className:"flex items-center justify-between bg-bg-secondary rounded-lg p-4 border border-border",children:[i.jsxs("div",{className:"flex-1",children:[i.jsxs("div",{className:"flex items-center gap-2",children:[i.jsx("span",{className:"px-2 py-0.5 bg-accent-primary/25 text-accent-primary rounded text-xs font-medium",children:$S(E.backend)}),i.jsx("span",{className:"text-text-primary font-medium",children:E.name}),i.jsx("span",{className:`text-xs px-1.5 py-0.5 rounded-full ${E.isLocal?"text-accent-success bg-accent-success/10":"text-accent-warning bg-accent-warning/10"}`,children:E.isLocal?"local":"api"})]}),i.jsx("p",{className:"text-text-muted text-sm mt-1",children:E.url}),E.model&&i.jsxs("p",{className:"text-text-secondary text-xs mt-0.5",children:["Model: ",E.model]})]}),i.jsx("div",{className:"flex items-center gap-1",children:m===E.id?i.jsxs("div",{className:"flex items-center gap-1",children:[i.jsx("button",{onClick:()=>_(E.id),disabled:f===E.id,className:"px-2 py-1 text-xs text-red-500 hover:text-red-400 bg-red-500/10 rounded transition-colors disabled:opacity-50",children:f===E.id?"Deleting...":"Confirm"}),i.jsx("button",{onClick:()=>x(null),className:"px-2 py-1 text-xs text-text-muted hover:text-text-secondary transition-colors",children:"Cancel"})]}):i.jsxs(i.Fragment,{children:[i.jsx("button",{onClick:()=>v(E),className:"px-2 py-1 text-xs text-text-muted hover:text-text-secondary border border-border rounded transition-colors",children:"Edit"}),i.jsx("button",{onClick:()=>x(E.id),className:"p-2 text-text-muted hover:text-red-500 transition-colors",title:"Remove provider",children:i.jsx(Qa,{})})]})})]},E.id))}):i.jsx("div",{className:"bg-bg-secondary rounded-lg p-8 text-center border border-border",children:i.jsx("p",{className:"text-text-muted",children:"No providers configured yet"})}),i.jsxs("button",{onClick:C,"data-testid":"onboarding-add-provider-button",className:"w-full flex items-center justify-center gap-2 px-4 py-3 bg-bg-secondary border border-dashed border-border rounded-lg text-text-secondary hover:text-text-primary hover:border-text-muted transition-colors",children:[i.jsx(ni,{className:"w-4 h-4"}),"Add Provider"]}),i.jsx("button",{onClick:b,disabled:!j,"data-testid":"onboarding-continue-button",className:"w-full mt-6 px-6 py-3 bg-accent-primary text-text-primary rounded-lg font-medium hover:bg-accent-primary/90 disabled:opacity-50 disabled:cursor-not-allowed transition-colors",children:"Continue"})]}),i.jsx(Nk,{isOpen:l,onClose:S,onSave:w,initialStep:1,editProvider:c??void 0})]})}function U$({onNext:e}){const[t,n]=A.useState(""),[r,o]=A.useState(!1);return A.useEffect(()=>{Se("/api/config").then(l=>l.json()).then(l=>{l.workdir?n(l.workdir):fetch("/api/directories?path="+encodeURIComponent("/home")).then(u=>u.json()).then(u=>{u.current&&n(u.current)}).catch(()=>{})}).catch(()=>{fetch("/api/directories?path="+encodeURIComponent("/home")).then(l=>l.json()).then(l=>{l.current&&n(l.current)}).catch(()=>{})})},[]),i.jsxs("div",{className:"max-w-xl mx-auto",children:[i.jsx("h2",{className:"text-2xl font-bold text-text-primary mb-2",children:"Your Projects Folder"}),i.jsx("p",{className:"text-text-secondary mb-8",children:"Where should OpenFox create project folders?"}),i.jsxs("div",{className:"space-y-4",children:[i.jsxs("div",{children:[i.jsx("label",{className:"block text-sm text-text-secondary mb-1",children:"Workspace directory"}),i.jsxs("div",{className:"flex gap-2",children:[i.jsx("input",{type:"text",value:t,onChange:l=>n(l.target.value),placeholder:"/home/user/projects","data-testid":"onboarding-workdir-input",className:"flex-1 px-4 py-2 bg-bg-secondary border border-border rounded-lg text-text-primary placeholder-text-muted focus:outline-none focus:border-accent-primary"}),i.jsx("button",{onClick:()=>o(!0),className:"px-4 py-2 bg-bg-secondary border border-border rounded-lg hover:border-text-muted",children:"Browse"})]})]}),r&&i.jsx(ld,{initialPath:t||void 0,onSelect:l=>{n(l),o(!1)},onClose:()=>o(!1)}),i.jsx("button",{onClick:()=>e({workdir:t}),disabled:!t,"data-testid":"onboarding-workdir-continue-button",className:"w-full mt-6 px-6 py-3 bg-accent-primary text-text-primary rounded-lg font-medium hover:bg-accent-primary/90 disabled:opacity-50 disabled:cursor-not-allowed transition-colors",children:"Continue"})]})]})}function F$({onNext:e}){const[t,n]=A.useState(!1),[r,o]=A.useState("http://localhost:11434"),[l,u]=A.useState("qwen3.5:0.8b"),[c,d]=A.useState("ollama"),{copied:f,copy:p}=dk();A.useEffect(()=>{Se("/api/config").then(x=>x.json()).then(x=>{x.visionFallback&&(n(x.visionFallback.enabled),o(x.visionFallback.url),u(x.visionFallback.model),x.visionFallback.backend&&d(x.visionFallback.backend))}).catch(()=>{})},[]);function m(x){if(x){e({});return}e({visionFallback:{enabled:t,url:r,model:l,timeout:120,backend:c}})}return i.jsxs("div",{className:"max-w-xl mx-auto",children:[i.jsx("h2",{className:"text-2xl font-bold text-text-primary mb-2",children:"Vision (Optional)"}),i.jsx("p",{className:"text-text-secondary mb-8",children:"Configure a vision model for non-vision models"}),i.jsxs("div",{className:"space-y-6",children:[i.jsxs("div",{className:"bg-bg-secondary rounded-lg p-4 border border-border",children:[i.jsx("p",{className:"text-text-secondary text-sm mb-2",children:"You need a server with a vision model. Choose your backend type below."}),i.jsx("p",{className:"text-text-secondary text-sm mb-2",children:"For Ollama:"}),i.jsx("a",{href:"https://ollama.com/download",target:"_blank",rel:"noopener noreferrer",className:"text-accent-primary hover:underline text-sm",children:"Download Ollama"}),i.jsxs("div",{className:"mt-3 p-2 bg-bg-primary rounded border border-border flex items-center justify-between gap-2",children:[i.jsx("code",{className:"text-text-secondary text-xs",children:"ollama pull qwen3.5:0.8b"}),i.jsx("button",{onClick:()=>p("ollama pull qwen3.5:0.8b"),className:"text-text-muted hover:text-text-primary transition-colors",title:"Copy",children:f?i.jsx(Wr,{className:"w-4 h-4 text-accent-primary"}):i.jsx(dN,{className:"w-4 h-4"})})]}),i.jsxs("p",{className:"text-text-secondary text-sm mt-3",children:["For OpenAI-compatible servers (vLLM, sglang, llama.cpp): use the ",i.jsx("strong",{children:"OpenAI"})," backend type."]})]}),i.jsxs("label",{className:"flex items-center gap-3 cursor-pointer",children:[i.jsx("input",{type:"checkbox",checked:t,onChange:x=>n(x.target.checked),className:"w-5 h-5 rounded border-border bg-bg-secondary text-accent-primary focus:ring-accent-primary"}),i.jsx("span",{className:"text-text-primary",children:"Enable vision fallback for non-vision models"})]}),t&&i.jsxs("div",{className:"space-y-4 pl-8",children:[i.jsxs("div",{children:[i.jsx("label",{className:"block text-sm text-text-secondary mb-1",children:"Backend type"}),i.jsxs("select",{value:c,onChange:x=>d(x.target.value),className:"w-full px-4 py-2 bg-bg-secondary border border-border rounded-lg text-text-primary focus:outline-none focus:border-accent-primary",children:[i.jsx("option",{value:"ollama",children:"Ollama"}),i.jsx("option",{value:"openai",children:"OpenAI-compatible (vLLM, sglang, llama.cpp)"})]})]}),i.jsxs("div",{children:[i.jsx("label",{className:"block text-sm text-text-secondary mb-1",children:"Vision server URL"}),i.jsx("input",{type:"text",value:r,onChange:x=>o(x.target.value),placeholder:c==="ollama"?"http://localhost:11434":"http://localhost:8000/v1",className:"w-full px-4 py-2 bg-bg-secondary border border-border rounded-lg text-text-primary placeholder-text-muted focus:outline-none focus:border-accent-primary"})]}),i.jsxs("div",{children:[i.jsx("label",{className:"block text-sm text-text-secondary mb-1",children:"Vision model name"}),i.jsx("input",{type:"text",value:l,onChange:x=>u(x.target.value),placeholder:c==="ollama"?"qwen3.5:0.8b":"qwen3.5-27b",className:"w-full px-4 py-2 bg-bg-secondary border border-border rounded-lg text-text-primary placeholder-text-muted focus:outline-none focus:border-accent-primary"})]})]}),i.jsxs("div",{className:"flex items-center justify-between pt-4",children:[i.jsx("button",{onClick:()=>m(!0),"data-testid":"onboarding-skip-button",className:"text-text-muted hover:text-text-secondary text-sm underline",children:"Skip for now"}),i.jsx("button",{onClick:()=>m(!1),className:"px-6 py-3 bg-accent-primary text-text-primary rounded-lg font-medium hover:bg-accent-primary/90 transition-colors",children:"Finish Setup"})]})]})]})}function V$({onComplete:e}){const[t,n]=A.useState(1),[r,o]=A.useState(!1),[l,u]=A.useState({});async function c(m){u(x=>({...x,providers:m.providers})),n(2)}async function d(m){u(x=>({...x,...m})),n(3)}async function f(m){o(!0);try{if(!(await Se("/api/init/config",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({workdir:l.workdir,visionFallback:m.visionFallback})})).ok)throw new Error("Failed to save config");e()}catch(x){console.error("Failed to save onboarding data:",x),o(!1)}}const p=m=>{n(m)};return i.jsxs("div",{className:"w-full max-w-xl mx-auto px-6 py-16 relative",children:[i.jsx(Ol,{onClick:e,className:"absolute top-4 right-4 p-2",variant:"modal",size:"xl"}),i.jsx(z$,{currentStep:t,totalSteps:3,labels:["LLM Providers","Projects Folder","Vision"],onStepClick:p}),i.jsx("div",{className:"max-w-xl mx-auto",children:r?i.jsxs("div",{className:"text-center",children:[i.jsx(ni,{className:"w-6 h-6"}),i.jsx("p",{className:"mt-4 text-text-secondary",children:"Saving your settings..."})]}):i.jsxs(i.Fragment,{children:[t===1&&i.jsx(H$,{onNext:c}),t===2&&i.jsx(U$,{onNext:d}),t===3&&i.jsx(F$,{onNext:f})]})})]})}const Gm="openfox_updated_to",Wm="update_pending";function G$(){const[e,t]=A.useState(!1),n=localStorage.getItem(Gm),r=localStorage.getItem(Wm);A.useEffect(()=>{if(!n||!r)return;const l=setTimeout(()=>{localStorage.removeItem(Gm),localStorage.removeItem(Wm),t(!0)},8e3);return()=>clearTimeout(l)},[n,r]);const o=()=>{localStorage.removeItem(Gm),localStorage.removeItem(Wm),t(!0)};return e||r!=="true"||!n?null:i.jsxs("div",{className:"fixed bottom-20 left-1/2 -translate-x-1/2 z-[100] flex items-center gap-3 px-4 py-2.5 bg-bg-secondary border border-border rounded-lg shadow-xl animate-slide-down",role:"status","aria-live":"polite",children:[i.jsx("div",{className:"flex items-center justify-center w-5 h-5 rounded-full bg-accent-primary/20",children:i.jsx(Wr,{className:"w-3 h-3 text-accent-primary"})}),i.jsxs("div",{className:"flex flex-col",children:[i.jsx("span",{className:"text-sm font-medium text-text-primary",children:"OpenFox updated successfully"}),i.jsxs("span",{className:"text-xs text-text-muted",children:["Now running ",n]})]}),i.jsx("button",{onClick:o,className:"ml-2 p-1 rounded hover:bg-bg-tertiary text-text-muted hover:text-text-primary transition-colors","aria-label":"Dismiss",children:i.jsx(ZS,{className:"w-3.5 h-3.5"})})]})}typeof window<"u"&&(Yt.getState().loadUserPresets(),Yt.getState().applySavedTheme());function Ag(){return typeof window>"u"?!1:localStorage.getItem("openfox_token")!==null}function Ak(){return i.jsx("div",{className:"flex-1 flex items-center justify-center",children:i.jsx(ri,{})})}function W$({sidebarOpen:e,onSidebarToggle:t}){const[,n]=Xa("/p/:projectId"),r=n==null?void 0:n.projectId,o=Re(d=>d.connectionStatus),l=Ut(d=>d.currentProject),u=Ag();return aN({canLoad:o==="connected"||u,projectId:r,currentProjectId:l==null?void 0:l.id}),!l||l.id!==r?i.jsx(Ak,{}):i.jsxs(i.Fragment,{children:[i.jsx(w1,{projectId:r,isOpen:e,onClose:t}),i.jsx("div",{className:"flex-1 min-w-0 bg-primary",children:i.jsx(IT,{})})]})}function q$({sidebarOpen:e,onSidebarToggle:t,rightSidebarOpen:n,onRightSidebarToggle:r}){const[,o]=Xa("/p/:projectId/s/:sessionId"),l=o==null?void 0:o.projectId,u=o==null?void 0:o.sessionId,[,c]=Gn(),d=Re(C=>C.connectionStatus),f=Re(C=>C.currentSession),p=Re(C=>C.error),m=Re(C=>C.clearError),x=Ut(C=>C.currentProject),y=Ag();return oN({canLoad:d==="connected"||y,projectId:l,sessionId:u,currentProjectId:x==null?void 0:x.id,currentSessionId:f==null?void 0:f.id}),A.useEffect(()=>{(p==null?void 0:p.code)==="NOT_FOUND"&&l&&(m(),c(`/p/${l}`))},[p,l,m,c]),!x||x.id!==l?i.jsx(Ak,{}):i.jsxs(i.Fragment,{children:[i.jsx(w1,{projectId:l,isOpen:e,onClose:t}),i.jsx("div",{className:"flex-1 min-w-0 bg-primary",children:i.jsx(B$,{criteriaSidebarOpen:n,onCriteriaSidebarToggle:r})})]})}function K$(){const e=un(r=>r.fetchConfig),[,t]=Gn();async function n(){await e(),t("/")}return i.jsx("div",{className:"flex-1 overflow-y-auto",children:i.jsx(V$,{onComplete:n})})}function Y$(){const{connectionStatus:e}=tN(),t=un(X=>X.fetchConfig),n=un(X=>X.refreshProviderModels),r=un(X=>X.providers),o=un(X=>X.activeProviderId),[,l]=Gn(),u=Ag(),[c,d]=A.useState(!1);A.useEffect(()=>{(e==="connected"||u)&&t().then(()=>{d(!0),tn.getState().getSettings([...Lp,Pe.DISPLAY_THEME,Pe.DISPLAY_USER_PRESETS,Pe.KEYBINDINGS])})},[e,u,t]),A.useEffect(()=>{c&&o&&n(o).then(()=>{const X=un.getState().defaultModelSelection;(X?X.split("/")[0]:null)!==o&&t()})},[c,o,n,t]);const f=tn(X=>X.settings);A.useEffect(()=>{c&&r.length===0&&l("/onboarding")},[c,r.length]),A.useEffect(()=>{const{applyPreset:X,applyTokens:z,setFollowSystemTheme:D,initSystemThemeListener:B}=Yt.getState(),q=f[Pe.DISPLAY_THEME],M=f[Pe.DISPLAY_USER_PRESETS],ee=f[Pe.DISPLAY_FOLLOW_SYSTEM_THEME];if(M&&localStorage.setItem("openfox:userPresets",M),q){localStorage.setItem("openfox:theme",q);try{const ne=JSON.parse(q);ne.preset&&ne.tokens?(X(ne.preset),Yt.setState({basePreset:ne.preset}),z(ne.tokens)):ne.preset?X(ne.preset):ne.tokens&&z(ne.tokens)}catch{X("dark")}}else X("system");ee!==void 0&&Yt.getState().followSystemTheme!==(ee==="true")&&D(ee==="true");const J=B();return()=>J()},[f[Pe.DISPLAY_THEME],f[Pe.DISPLAY_USER_PRESETS]]);const p=()=>{const X=localStorage.getItem("openfox:leftSidebar");return X!==null?X==="true":!0},m=()=>{const X=localStorage.getItem("openfox:rightSidebar");return X!==null?X==="true":!0},[x,y]=A.useState(p),[w,C]=A.useState(m),[v,S]=A.useState(!1),[_,b]=A.useState(!1),[j,E]=A.useState(!1),T=l2();A.useEffect(()=>{const X=()=>{E(window.innerWidth<768)};return X(),window.addEventListener("resize",X),()=>window.removeEventListener("resize",X)},[]);const[R]=Gn(),L=/^\/p\/[^/]+$/.test(R),O=j?v:L?!0:x,P=j?_:w,G=()=>{j?S(!v):y(!x)},W=()=>{j?b(!_):C(!w)};A.useEffect(()=>{j||localStorage.setItem("openfox:leftSidebar",String(x))},[x,j]),A.useEffect(()=>{j||localStorage.setItem("openfox:rightSidebar",String(w))},[w,j]),A.useEffect(()=>{(e==="connected"||u)&&t()},[e,t,u]);const I=Re(X=>X.showPasswordModal),H=Re(X=>X.passwordModalRetry),V=Re(X=>X.submitPassword),U=Re(X=>X.cancelPassword),[Q]=Xa("/p/:projectId/s/:sessionId/readonly");return!Q&&e!=="connected"&&!I&&!u?i.jsxs(i.Fragment,{children:[i.jsx(TS,{isOpen:!0,isRetry:H,onSubmit:V,onCancel:U}),i.jsx("div",{className:"h-screen flex items-center justify-center",children:i.jsx($N,{text:"Connecting to server..."})})]}):Q?i.jsx($$,{}):i.jsxs(i.Fragment,{children:[i.jsx(TS,{isOpen:I,isRetry:H,onSubmit:V,onCancel:U}),i.jsxs("div",{className:"flex flex-col",style:{height:j?`calc(${T.offsetTop}px + ${T.height}px)`:"100vh"},children:[i.jsx(LT,{}),i.jsx(kT,{onMenuClick:G,onCriteriaToggle:W}),i.jsx("div",{className:"flex-1 flex overflow-hidden",children:i.jsxs(A2,{children:[i.jsx(Qo,{path:"/onboarding",children:i.jsx(K$,{})}),i.jsx(Qo,{path:"/p/:projectId/s/:sessionId",children:i.jsx(q$,{sidebarOpen:O,onSidebarToggle:G,rightSidebarOpen:P,onRightSidebarToggle:W})}),i.jsx(Qo,{path:"/p/:projectId/new",children:i.jsx(OT,{})}),i.jsx(Qo,{path:"/p/:projectId",children:i.jsx(W$,{sidebarOpen:O,onSidebarToggle:G})}),i.jsx(Qo,{path:"/",children:i.jsx(DT,{})})]})})]}),i.jsx(G$,{})]})}r2.createRoot(document.getElementById("root")).render(i.jsx(Xs.StrictMode,{children:i.jsx(Y$,{})}));
305
+ ${We.prompt}`:We.prompt;We.metadata.agentMode&&Re.getState().switchMode(We.metadata.agentMode),F(Ee,l!=null&&l.length?l:void 0,{messageKind:"command",isSystemGenerated:!0}),Ae()}},onSelectWorkflow:Ne=>{const Te=r.trim()||void 0,We=l.length>0?l:void 0;te(Te,We,Ne),Ae()}})]}),S&&i.jsx(q8,{isOpen:S,onClose:()=>{_(!1),Jm()},displayItems:ee,onNavigate:me})]})}function $$(){var S;const[,e]=Xa("/p/:projectId/s/:sessionId/readonly"),t=e==null?void 0:e.sessionId,[n,r]=A.useState(null),[o,l]=A.useState([]),[u,c]=A.useState(!0),[d,f]=A.useState(null),p=async()=>{if(t){c(!0),f(null);try{const _=await Se(`/api/sessions/${t}`);if(!_.ok){f(`Failed to load session (${_.status})`),c(!1);return}const b=await _.json();r(b.session??null),l(b.messages??[])}catch(_){f(_ instanceof Error?_.message:"Unknown error")}finally{c(!1)}}};A.useEffect(()=>{tn.getState().getSettings([...Lp])},[]),A.useEffect(()=>{p()},[t]);const{showThinking:m,showVerboseToolOutput:x,showStats:y,showAgentDefinitions:w,showWorkflowBars:C}=zi(),v=A.useMemo(()=>Tk(o),[o]);return u?i.jsx("div",{className:"h-screen flex items-center justify-center bg-primary",children:i.jsx(ri,{})}):d?i.jsx("div",{className:"h-screen flex items-center justify-center bg-primary",children:i.jsxs("div",{className:"text-center space-y-4",children:[i.jsx("div",{className:"text-red-400 text-sm",children:d}),i.jsx("button",{onClick:p,className:"px-3 py-1.5 text-sm bg-bg-tertiary text-text-primary border border-border rounded hover:bg-bg-tertiary/80 transition-colors",children:"Retry"})]})}):i.jsxs("div",{className:"h-screen print:h-auto flex flex-col bg-primary",children:[i.jsxs("div",{className:"flex items-center justify-between px-4 py-2 border-b border-border bg-secondary shrink-0 print:hidden",children:[i.jsxs("div",{className:"flex items-center gap-3 min-w-0",children:[i.jsxs("h1",{className:"text-sm font-medium text-text-primary truncate",children:[((S=n==null?void 0:n.metadata)==null?void 0:S.title)??"Session"," — Read-only view"]}),i.jsxs("span",{className:"text-xs text-text-muted whitespace-nowrap",children:[o.length," messages"]})]}),i.jsx("div",{className:"flex items-center gap-2",children:i.jsx("button",{onClick:p,disabled:u,className:"px-3 py-1 text-xs bg-bg-tertiary text-text-primary border border-border rounded hover:bg-bg-tertiary/80 transition-colors disabled:opacity-50",children:u?"Refreshing...":"Refresh"})})]}),i.jsxs("div",{className:"flex-1 overflow-y-auto print:overflow-visible",children:[i.jsx("div",{className:"pt-4",children:i.jsx(yk,{displayItems:v,showThinking:m,showVerboseToolOutput:x,showStats:y,showAgentDefinitions:w,showWorkflowBars:C})}),i.jsx("div",{className:"h-8"})]})]})}function TS({isOpen:e,isRetry:t,onSubmit:n,onCancel:r}){const[o,l]=A.useState(""),u=A.useRef(null);A.useEffect(()=>{e&&(l(""),setTimeout(()=>{var d;return(d=u.current)==null?void 0:d.focus()},100))},[e]);const c=d=>{d.preventDefault(),o.trim()&&n(o)};return i.jsx(At,{isOpen:e,onClose:r,title:t?"Invalid Password":"Password Required",size:"sm",children:i.jsxs("form",{onSubmit:c,className:"space-y-4",children:[i.jsx("p",{className:"text-text-secondary text-sm",children:t?"The password you entered was incorrect. Please try again.":"This server requires a password to connect."}),i.jsx(Mi,{ref:u,type:"password",value:o,onChange:d=>l(d.target.value),placeholder:"Enter password",autoFocus:!0}),i.jsxs("div",{className:"flex justify-end gap-2",children:[i.jsx(tt,{type:"button",variant:"secondary",onClick:r,children:"Cancel"}),i.jsx(tt,{type:"submit",disabled:!o.trim(),children:t?"Try Again":"Connect"})]})]})})}function z$({currentStep:e,totalSteps:t,labels:n,onStepClick:r}){return i.jsx("div",{className:"flex justify-center py-6",children:i.jsx("div",{className:"flex items-center",children:Array.from({length:t},(o,l)=>{const u=l+1,c=u<e,d=u===e;return i.jsxs("div",{className:"flex items-center",children:[i.jsx("button",{onClick:()=>r==null?void 0:r(u),className:`size-8 rounded-full flex items-center justify-center text-sm font-medium transition-colors shrink-0 ${c?"bg-accent-primary text-text-primary hover:opacity-80":d?"bg-accent-primary text-text-primary":"bg-bg-tertiary text-text-muted"}`,children:c?"✓":u}),i.jsx("button",{onClick:()=>r==null?void 0:r(u),className:`ml-2 mr-4 text-sm whitespace-nowrap hidden sm:block ${d?"text-text-primary font-medium":"text-text-muted hover:text-text-secondary"}`,children:n[l]}),l<t-1&&i.jsx("div",{className:`w-12 sm:w-20 h-0.5 mr-4 ${c?"bg-accent-primary":"bg-border"}`})]},l)})})})}function H$({onNext:e}){const[t,n]=A.useState([]),[r,o]=A.useState([]),[l,u]=A.useState(!1),[c,d]=A.useState(null),[f,p]=A.useState(null),[m,x]=A.useState(null);A.useEffect(()=>{y()},[]);async function y(){try{const E=await Se("/api/providers");if(E.ok){const R=(await E.json()).providers.map(L=>({id:L.id,name:L.name,url:L.url,backend:L.backend,model:null,apiKey:L.apiKey,isLocal:L.isLocal,thinkingField:L.thinkingField,models:L.models}));n(R),o(R)}}catch{}}async function w(E){const T=E.id.startsWith("temp-"),R=r.some(P=>P.id===E.id),L=r.length===0&&c===null,O=jk(E);try{let P;if(T){const W=await Se("/api/providers",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(O)});if(!W.ok)throw new Error("Failed to create provider");const I=await W.json();P={...E,id:I.provider.id,model:null}}else{if(!(await Se(`/api/providers/${E.id}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(O)})).ok)throw new Error("Failed to update provider");P={...E,model:null}}const G=W=>W.some(I=>I.id===P.id)?W.map(I=>I.id===P.id?P:I):[...W,P];o(G),n(G),L&&!R&&e({providers:[P]})}catch{if(T){const P={...E,model:null};o(G=>[...G,P])}}}function C(){d(null),u(!0)}function v(E){d(E),u(!0)}function S(){u(!1),d(null)}function _(E){p(E),t.some(R=>R.id===E)?Se(`/api/providers/${E}`,{method:"DELETE"}).then(()=>{o(r.filter(R=>R.id!==E)),n(t.filter(R=>R.id!==E)),p(null)}).catch(()=>p(null)):(o(r.filter(R=>R.id!==E)),p(null))}function b(){const E=r.filter(T=>!T.id.startsWith("temp-"));e({providers:E})}const j=r.length>0;return i.jsxs("div",{className:"max-w-xl mx-auto",children:[i.jsx("h2",{className:"text-2xl font-bold text-text-primary mb-2",children:"LLM Providers"}),i.jsx("p",{className:"text-text-secondary mb-8",children:"Manage your LLM server connections"}),i.jsxs("div",{className:"space-y-4",children:[r.length>0?i.jsx("div",{className:"space-y-2",children:r.map(E=>i.jsxs("div",{className:"flex items-center justify-between bg-bg-secondary rounded-lg p-4 border border-border",children:[i.jsxs("div",{className:"flex-1 min-w-0",children:[i.jsxs("div",{className:"flex items-center gap-2",children:[i.jsx("span",{className:"px-2 py-0.5 bg-accent-primary/25 text-accent-primary rounded text-xs font-medium",children:$S(E.backend)}),i.jsx("span",{className:"text-text-primary font-medium",children:E.name}),i.jsx("span",{className:`text-xs px-1.5 py-0.5 rounded-full ${E.isLocal?"text-accent-success bg-accent-success/10":"text-accent-warning bg-accent-warning/10"}`,children:E.isLocal?"local":"api"})]}),i.jsx("p",{className:"text-text-muted text-sm mt-1 truncate",children:E.url}),E.model&&i.jsxs("p",{className:"text-text-secondary text-xs mt-0.5",children:["Model: ",E.model]})]}),i.jsx("div",{className:"flex items-center gap-1",children:m===E.id?i.jsxs("div",{className:"flex items-center gap-1",children:[i.jsx("button",{onClick:()=>_(E.id),disabled:f===E.id,className:"px-2 py-1 text-xs text-red-500 hover:text-red-400 bg-red-500/10 rounded transition-colors disabled:opacity-50",children:f===E.id?"Deleting...":"Confirm"}),i.jsx("button",{onClick:()=>x(null),className:"px-2 py-1 text-xs text-text-muted hover:text-text-secondary transition-colors",children:"Cancel"})]}):i.jsxs(i.Fragment,{children:[i.jsx("button",{onClick:()=>v(E),className:"px-2 py-1 text-xs text-text-muted hover:text-text-secondary border border-border rounded transition-colors",children:"Edit"}),i.jsx("button",{onClick:()=>x(E.id),className:"p-2 text-text-muted hover:text-red-500 transition-colors",title:"Remove provider",children:i.jsx(Qa,{})})]})})]},E.id))}):i.jsx("div",{className:"bg-bg-secondary rounded-lg p-8 text-center border border-border",children:i.jsx("p",{className:"text-text-muted",children:"No providers configured yet"})}),i.jsxs("button",{onClick:C,"data-testid":"onboarding-add-provider-button",className:"w-full flex items-center justify-center gap-2 px-4 py-3 bg-bg-secondary border border-dashed border-border rounded-lg text-text-secondary hover:text-text-primary hover:border-text-muted transition-colors",children:[i.jsx(ni,{className:"w-4 h-4"}),"Add Provider"]}),i.jsx("button",{onClick:b,disabled:!j,"data-testid":"onboarding-continue-button",className:"w-full mt-6 px-6 py-3 bg-accent-primary text-text-primary rounded-lg font-medium hover:bg-accent-primary/90 disabled:opacity-50 disabled:cursor-not-allowed transition-colors",children:"Continue"})]}),i.jsx(Nk,{isOpen:l,onClose:S,onSave:w,initialStep:1,editProvider:c??void 0})]})}function U$({onNext:e}){const[t,n]=A.useState(""),[r,o]=A.useState(!1);return A.useEffect(()=>{Se("/api/config").then(l=>l.json()).then(l=>{l.workdir?n(l.workdir):fetch("/api/directories?path="+encodeURIComponent("/home")).then(u=>u.json()).then(u=>{u.current&&n(u.current)}).catch(()=>{})}).catch(()=>{fetch("/api/directories?path="+encodeURIComponent("/home")).then(l=>l.json()).then(l=>{l.current&&n(l.current)}).catch(()=>{})})},[]),i.jsxs("div",{className:"max-w-xl mx-auto",children:[i.jsx("h2",{className:"text-2xl font-bold text-text-primary mb-2",children:"Your Projects Folder"}),i.jsx("p",{className:"text-text-secondary mb-8",children:"Where should OpenFox create project folders?"}),i.jsxs("div",{className:"space-y-4",children:[i.jsxs("div",{children:[i.jsx("label",{className:"block text-sm text-text-secondary mb-1",children:"Workspace directory"}),i.jsxs("div",{className:"flex gap-2",children:[i.jsx("input",{type:"text",value:t,onChange:l=>n(l.target.value),placeholder:"/home/user/projects","data-testid":"onboarding-workdir-input",className:"flex-1 px-4 py-2 bg-bg-secondary border border-border rounded-lg text-text-primary placeholder-text-muted focus:outline-none focus:border-accent-primary"}),i.jsx("button",{onClick:()=>o(!0),className:"px-4 py-2 bg-bg-secondary border border-border rounded-lg hover:border-text-muted",children:"Browse"})]})]}),r&&i.jsx(ld,{initialPath:t||void 0,onSelect:l=>{n(l),o(!1)},onClose:()=>o(!1)}),i.jsx("button",{onClick:()=>e({workdir:t}),disabled:!t,"data-testid":"onboarding-workdir-continue-button",className:"w-full mt-6 px-6 py-3 bg-accent-primary text-text-primary rounded-lg font-medium hover:bg-accent-primary/90 disabled:opacity-50 disabled:cursor-not-allowed transition-colors",children:"Continue"})]})]})}function F$({onNext:e}){const[t,n]=A.useState(!1),[r,o]=A.useState("http://localhost:11434"),[l,u]=A.useState("qwen3.5:0.8b"),[c,d]=A.useState("ollama"),{copied:f,copy:p}=dk();A.useEffect(()=>{Se("/api/config").then(x=>x.json()).then(x=>{x.visionFallback&&(n(x.visionFallback.enabled),o(x.visionFallback.url),u(x.visionFallback.model),x.visionFallback.backend&&d(x.visionFallback.backend))}).catch(()=>{})},[]);function m(x){if(x){e({});return}e({visionFallback:{enabled:t,url:r,model:l,timeout:120,backend:c}})}return i.jsxs("div",{className:"max-w-xl mx-auto",children:[i.jsx("h2",{className:"text-2xl font-bold text-text-primary mb-2",children:"Vision (Optional)"}),i.jsx("p",{className:"text-text-secondary mb-8",children:"Configure a vision model for non-vision models"}),i.jsxs("div",{className:"space-y-6",children:[i.jsxs("div",{className:"bg-bg-secondary rounded-lg p-4 border border-border",children:[i.jsx("p",{className:"text-text-secondary text-sm mb-2",children:"You need a server with a vision model. Choose your backend type below."}),i.jsx("p",{className:"text-text-secondary text-sm mb-2",children:"For Ollama:"}),i.jsx("a",{href:"https://ollama.com/download",target:"_blank",rel:"noopener noreferrer",className:"text-accent-primary hover:underline text-sm",children:"Download Ollama"}),i.jsxs("div",{className:"mt-3 p-2 bg-bg-primary rounded border border-border flex items-center justify-between gap-2",children:[i.jsx("code",{className:"text-text-secondary text-xs",children:"ollama pull qwen3.5:0.8b"}),i.jsx("button",{onClick:()=>p("ollama pull qwen3.5:0.8b"),className:"text-text-muted hover:text-text-primary transition-colors",title:"Copy",children:f?i.jsx(Wr,{className:"w-4 h-4 text-accent-primary"}):i.jsx(dN,{className:"w-4 h-4"})})]}),i.jsxs("p",{className:"text-text-secondary text-sm mt-3",children:["For OpenAI-compatible servers (vLLM, sglang, llama.cpp): use the ",i.jsx("strong",{children:"OpenAI"})," backend type."]})]}),i.jsxs("label",{className:"flex items-center gap-3 cursor-pointer",children:[i.jsx("input",{type:"checkbox",checked:t,onChange:x=>n(x.target.checked),className:"w-5 h-5 rounded border-border bg-bg-secondary text-accent-primary focus:ring-accent-primary"}),i.jsx("span",{className:"text-text-primary",children:"Enable vision fallback for non-vision models"})]}),t&&i.jsxs("div",{className:"space-y-4 pl-8",children:[i.jsxs("div",{children:[i.jsx("label",{className:"block text-sm text-text-secondary mb-1",children:"Backend type"}),i.jsxs("select",{value:c,onChange:x=>d(x.target.value),className:"w-full px-4 py-2 bg-bg-secondary border border-border rounded-lg text-text-primary focus:outline-none focus:border-accent-primary",children:[i.jsx("option",{value:"ollama",children:"Ollama"}),i.jsx("option",{value:"openai",children:"OpenAI-compatible (vLLM, sglang, llama.cpp)"})]})]}),i.jsxs("div",{children:[i.jsx("label",{className:"block text-sm text-text-secondary mb-1",children:"Vision server URL"}),i.jsx("input",{type:"text",value:r,onChange:x=>o(x.target.value),placeholder:c==="ollama"?"http://localhost:11434":"http://localhost:8000/v1",className:"w-full px-4 py-2 bg-bg-secondary border border-border rounded-lg text-text-primary placeholder-text-muted focus:outline-none focus:border-accent-primary"})]}),i.jsxs("div",{children:[i.jsx("label",{className:"block text-sm text-text-secondary mb-1",children:"Vision model name"}),i.jsx("input",{type:"text",value:l,onChange:x=>u(x.target.value),placeholder:c==="ollama"?"qwen3.5:0.8b":"qwen3.5-27b",className:"w-full px-4 py-2 bg-bg-secondary border border-border rounded-lg text-text-primary placeholder-text-muted focus:outline-none focus:border-accent-primary"})]})]}),i.jsxs("div",{className:"flex items-center justify-between pt-4",children:[i.jsx("button",{onClick:()=>m(!0),"data-testid":"onboarding-skip-button",className:"text-text-muted hover:text-text-secondary text-sm underline",children:"Skip for now"}),i.jsx("button",{onClick:()=>m(!1),className:"px-6 py-3 bg-accent-primary text-text-primary rounded-lg font-medium hover:bg-accent-primary/90 transition-colors",children:"Finish Setup"})]})]})]})}function V$({onComplete:e}){const[t,n]=A.useState(1),[r,o]=A.useState(!1),[l,u]=A.useState({});async function c(m){u(x=>({...x,providers:m.providers})),n(2)}async function d(m){u(x=>({...x,...m})),n(3)}async function f(m){o(!0);try{if(!(await Se("/api/init/config",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({workdir:l.workdir,visionFallback:m.visionFallback})})).ok)throw new Error("Failed to save config");e()}catch(x){console.error("Failed to save onboarding data:",x),o(!1)}}const p=m=>{n(m)};return i.jsxs("div",{className:"w-full max-w-xl mx-auto px-6 py-16 relative",children:[i.jsx(Ol,{onClick:e,className:"absolute top-4 right-4 p-2",variant:"modal",size:"xl"}),i.jsx(z$,{currentStep:t,totalSteps:3,labels:["LLM Providers","Projects Folder","Vision"],onStepClick:p}),i.jsx("div",{className:"max-w-xl mx-auto",children:r?i.jsxs("div",{className:"text-center",children:[i.jsx(ni,{className:"w-6 h-6"}),i.jsx("p",{className:"mt-4 text-text-secondary",children:"Saving your settings..."})]}):i.jsxs(i.Fragment,{children:[t===1&&i.jsx(H$,{onNext:c}),t===2&&i.jsx(U$,{onNext:d}),t===3&&i.jsx(F$,{onNext:f})]})})]})}const Gm="openfox_updated_to",Wm="update_pending";function G$(){const[e,t]=A.useState(!1),n=localStorage.getItem(Gm),r=localStorage.getItem(Wm);A.useEffect(()=>{if(!n||!r)return;const l=setTimeout(()=>{localStorage.removeItem(Gm),localStorage.removeItem(Wm),t(!0)},8e3);return()=>clearTimeout(l)},[n,r]);const o=()=>{localStorage.removeItem(Gm),localStorage.removeItem(Wm),t(!0)};return e||r!=="true"||!n?null:i.jsxs("div",{className:"fixed bottom-20 left-1/2 -translate-x-1/2 z-[100] flex items-center gap-3 px-4 py-2.5 bg-bg-secondary border border-border rounded-lg shadow-xl animate-slide-down",role:"status","aria-live":"polite",children:[i.jsx("div",{className:"flex items-center justify-center w-5 h-5 rounded-full bg-accent-primary/20",children:i.jsx(Wr,{className:"w-3 h-3 text-accent-primary"})}),i.jsxs("div",{className:"flex flex-col",children:[i.jsx("span",{className:"text-sm font-medium text-text-primary",children:"OpenFox updated successfully"}),i.jsxs("span",{className:"text-xs text-text-muted",children:["Now running ",n]})]}),i.jsx("button",{onClick:o,className:"ml-2 p-1 rounded hover:bg-bg-tertiary text-text-muted hover:text-text-primary transition-colors","aria-label":"Dismiss",children:i.jsx(ZS,{className:"w-3.5 h-3.5"})})]})}typeof window<"u"&&(Yt.getState().loadUserPresets(),Yt.getState().applySavedTheme());function Ag(){return typeof window>"u"?!1:localStorage.getItem("openfox_token")!==null}function Ak(){return i.jsx("div",{className:"flex-1 flex items-center justify-center",children:i.jsx(ri,{})})}function W$({sidebarOpen:e,onSidebarToggle:t}){const[,n]=Xa("/p/:projectId"),r=n==null?void 0:n.projectId,o=Re(d=>d.connectionStatus),l=Ut(d=>d.currentProject),u=Ag();return aN({canLoad:o==="connected"||u,projectId:r,currentProjectId:l==null?void 0:l.id}),!l||l.id!==r?i.jsx(Ak,{}):i.jsxs(i.Fragment,{children:[i.jsx(w1,{projectId:r,isOpen:e,onClose:t}),i.jsx("div",{className:"flex-1 min-w-0 bg-primary",children:i.jsx(IT,{})})]})}function q$({sidebarOpen:e,onSidebarToggle:t,rightSidebarOpen:n,onRightSidebarToggle:r}){const[,o]=Xa("/p/:projectId/s/:sessionId"),l=o==null?void 0:o.projectId,u=o==null?void 0:o.sessionId,[,c]=Gn(),d=Re(C=>C.connectionStatus),f=Re(C=>C.currentSession),p=Re(C=>C.error),m=Re(C=>C.clearError),x=Ut(C=>C.currentProject),y=Ag();return oN({canLoad:d==="connected"||y,projectId:l,sessionId:u,currentProjectId:x==null?void 0:x.id,currentSessionId:f==null?void 0:f.id}),A.useEffect(()=>{(p==null?void 0:p.code)==="NOT_FOUND"&&l&&(m(),c(`/p/${l}`))},[p,l,m,c]),!x||x.id!==l?i.jsx(Ak,{}):i.jsxs(i.Fragment,{children:[i.jsx(w1,{projectId:l,isOpen:e,onClose:t}),i.jsx("div",{className:"flex-1 min-w-0 bg-primary",children:i.jsx(B$,{criteriaSidebarOpen:n,onCriteriaSidebarToggle:r})})]})}function K$(){const e=un(r=>r.fetchConfig),[,t]=Gn();async function n(){await e(),t("/")}return i.jsx("div",{className:"flex-1 overflow-y-auto",children:i.jsx(V$,{onComplete:n})})}function Y$(){const{connectionStatus:e}=tN(),t=un(X=>X.fetchConfig),n=un(X=>X.refreshProviderModels),r=un(X=>X.providers),o=un(X=>X.activeProviderId),[,l]=Gn(),u=Ag(),[c,d]=A.useState(!1);A.useEffect(()=>{(e==="connected"||u)&&t().then(()=>{d(!0),tn.getState().getSettings([...Lp,Pe.DISPLAY_THEME,Pe.DISPLAY_USER_PRESETS,Pe.KEYBINDINGS])})},[e,u,t]),A.useEffect(()=>{c&&o&&n(o).then(()=>{const X=un.getState().defaultModelSelection;(X?X.split("/")[0]:null)!==o&&t()})},[c,o,n,t]);const f=tn(X=>X.settings);A.useEffect(()=>{c&&r.length===0&&l("/onboarding")},[c,r.length]),A.useEffect(()=>{const{applyPreset:X,applyTokens:z,setFollowSystemTheme:D,initSystemThemeListener:B}=Yt.getState(),q=f[Pe.DISPLAY_THEME],M=f[Pe.DISPLAY_USER_PRESETS],ee=f[Pe.DISPLAY_FOLLOW_SYSTEM_THEME];if(M&&localStorage.setItem("openfox:userPresets",M),q){localStorage.setItem("openfox:theme",q);try{const ne=JSON.parse(q);ne.preset&&ne.tokens?(X(ne.preset),Yt.setState({basePreset:ne.preset}),z(ne.tokens)):ne.preset?X(ne.preset):ne.tokens&&z(ne.tokens)}catch{X("dark")}}else X("system");ee!==void 0&&Yt.getState().followSystemTheme!==(ee==="true")&&D(ee==="true");const J=B();return()=>J()},[f[Pe.DISPLAY_THEME],f[Pe.DISPLAY_USER_PRESETS]]);const p=()=>{const X=localStorage.getItem("openfox:leftSidebar");return X!==null?X==="true":!0},m=()=>{const X=localStorage.getItem("openfox:rightSidebar");return X!==null?X==="true":!0},[x,y]=A.useState(p),[w,C]=A.useState(m),[v,S]=A.useState(!1),[_,b]=A.useState(!1),[j,E]=A.useState(!1),T=l2();A.useEffect(()=>{const X=()=>{E(window.innerWidth<768)};return X(),window.addEventListener("resize",X),()=>window.removeEventListener("resize",X)},[]);const[R]=Gn(),L=/^\/p\/[^/]+$/.test(R),O=j?v:L?!0:x,P=j?_:w,G=()=>{j?S(!v):y(!x)},W=()=>{j?b(!_):C(!w)};A.useEffect(()=>{j||localStorage.setItem("openfox:leftSidebar",String(x))},[x,j]),A.useEffect(()=>{j||localStorage.setItem("openfox:rightSidebar",String(w))},[w,j]),A.useEffect(()=>{(e==="connected"||u)&&t()},[e,t,u]);const I=Re(X=>X.showPasswordModal),H=Re(X=>X.passwordModalRetry),V=Re(X=>X.submitPassword),U=Re(X=>X.cancelPassword),[Q]=Xa("/p/:projectId/s/:sessionId/readonly");return!Q&&e!=="connected"&&!I&&!u?i.jsxs(i.Fragment,{children:[i.jsx(TS,{isOpen:!0,isRetry:H,onSubmit:V,onCancel:U}),i.jsx("div",{className:"h-screen flex items-center justify-center",children:i.jsx($N,{text:"Connecting to server..."})})]}):Q?i.jsx($$,{}):i.jsxs(i.Fragment,{children:[i.jsx(TS,{isOpen:I,isRetry:H,onSubmit:V,onCancel:U}),i.jsxs("div",{className:"flex flex-col",style:{height:j?`calc(${T.offsetTop}px + ${T.height}px)`:"100vh"},children:[i.jsx(LT,{}),i.jsx(kT,{onMenuClick:G,onCriteriaToggle:W}),i.jsx("div",{className:"flex-1 flex overflow-hidden",children:i.jsxs(A2,{children:[i.jsx(Qo,{path:"/onboarding",children:i.jsx(K$,{})}),i.jsx(Qo,{path:"/p/:projectId/s/:sessionId",children:i.jsx(q$,{sidebarOpen:O,onSidebarToggle:G,rightSidebarOpen:P,onRightSidebarToggle:W})}),i.jsx(Qo,{path:"/p/:projectId/new",children:i.jsx(OT,{})}),i.jsx(Qo,{path:"/p/:projectId",children:i.jsx(W$,{sidebarOpen:O,onSidebarToggle:G})}),i.jsx(Qo,{path:"/",children:i.jsx(DT,{})})]})})]}),i.jsx(G$,{})]})}r2.createRoot(document.getElementById("root")).render(i.jsx(Xs.StrictMode,{children:i.jsx(Y$,{})}));