openfox 2.0.83 → 2.0.85

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 (60) hide show
  1. package/dist/{chat-handler-6KBOE4YA.js → chat-handler-3CWMOIOR.js} +15 -14
  2. package/dist/{chunk-3D3N2PXI.js → chunk-2KKFOVK7.js} +2 -2
  3. package/dist/{chunk-JKZPMRH2.js → chunk-3JYPDZT2.js} +2 -2
  4. package/dist/{chunk-JXTHW3YX.js → chunk-7PZBCATU.js} +18 -4
  5. package/dist/chunk-7WAOMWR3.js +7 -0
  6. package/dist/{chunk-IIRXKSB5.js → chunk-ACL4YUJH.js} +10 -2
  7. package/dist/{chunk-7ROIY3QN.js → chunk-DLJYYWM2.js} +169 -111
  8. package/dist/{chunk-D324ULDG.js → chunk-FTJ7U3VN.js} +20 -17
  9. package/dist/chunk-FYYPQ27K.js +399 -0
  10. package/dist/{chunk-KMGVUOLT.js → chunk-GLRTJJOB.js} +23 -20
  11. package/dist/{chunk-FVY2JOTO.js → chunk-H765CIHN.js} +2 -2
  12. package/dist/{chunk-AANVMTYU.js → chunk-L4S5N3WV.js} +8 -3
  13. package/dist/{chunk-VB23QPW3.js → chunk-M6X72DYZ.js} +3 -3
  14. package/dist/{chunk-SBSQD7MG.js → chunk-MTZ3PC6K.js} +2 -2
  15. package/dist/{chunk-NH2PVB6R.js → chunk-N54PQSCH.js} +33 -24
  16. package/dist/{chunk-A2IZ4PWQ.js → chunk-OHKBGMLO.js} +15 -4
  17. package/dist/{chunk-OBQN5ATP.js → chunk-RSO2HKNH.js} +98 -365
  18. package/dist/{chunk-WL6AOKRD.js → chunk-SGFQWQCE.js} +10 -8
  19. package/dist/{chunk-CNJ63FXJ.js → chunk-STFIEU5F.js} +3 -2
  20. package/dist/{chunk-BUXIESO5.js → chunk-V5LOH363.js} +6 -74
  21. package/dist/{chunk-5ZHVQOI3.js → chunk-W23S3TU5.js} +2 -2
  22. package/dist/{chunk-DQP5HSDS.js → chunk-WVMOGE7U.js} +3 -3
  23. package/dist/{chunk-HLZUN7OR.js → chunk-XXII6DS3.js} +7 -7
  24. package/dist/cli/dev.js +1 -1
  25. package/dist/cli/index.js +1 -1
  26. package/dist/{client-TA2VD4LR.js → client-C2P67MA4.js} +4 -4
  27. package/dist/{compactor-YKESKGHL.js → compactor-2YT66FDZ.js} +10 -8
  28. package/dist/{config-EN3WEH4A.js → config-JN6MW5SL.js} +2 -2
  29. package/dist/{events-GF2WNELM.js → events-OEDAFNEI.js} +7 -4
  30. package/dist/{folding-UACKBHUZ.js → folding-FGTCP73N.js} +7 -2
  31. package/dist/{http-client-QZY7W36Q.js → http-client-I52X7GQB.js} +3 -3
  32. package/dist/{manager-WOUOQVLV.js → manager-TD2UT62O.js} +4 -4
  33. package/dist/{orchestrator-BO62JYFM.js → orchestrator-6RYJYR3T.js} +14 -13
  34. package/dist/package.json +1 -1
  35. package/dist/{path-security-AWDNKRZ4.js → path-security-7ZNIG3ZE.js} +8 -5
  36. package/dist/{platform-7AK5MB4K.js → platform-OYKGQ7Z3.js} +3 -3
  37. package/dist/{processor-BLGEVOPK.js → processor-IGRFA3KA.js} +15 -14
  38. package/dist/{protocol-9WP7lLec.d.ts → protocol-5NJx1N4c.d.ts} +1 -1
  39. package/dist/provider/index.d.ts +4 -4
  40. package/dist/{provider-QVVJ6XNZ.js → provider-YNYYAR6C.js} +7 -7
  41. package/dist/{provider-manager-7246YSJT.js → provider-manager-3DW3A2VC.js} +5 -5
  42. package/dist/{serve-HXV2RX3Q.js → serve-LFC7D5B7.js} +21 -20
  43. package/dist/server/index.d.ts +4 -4
  44. package/dist/server/index.js +20 -19
  45. package/dist/{server-V4VA4A2E.js → server-E5IA4SK7.js} +16 -15
  46. package/dist/{sessions-SFG42M4W.js → sessions-V3BF2OTU.js} +5 -2
  47. package/dist/{settings-6TJIHDVX.js → settings-AGNYWEIE.js} +2 -2
  48. package/dist/shared/index.d.ts +3 -3
  49. package/dist/{tools-X4YLRR2Y.js → tools-ZUTPBREL.js} +13 -12
  50. package/dist/{types-ulRvCqQX.d.ts → types-B4wa_vGm.d.ts} +2 -0
  51. package/dist/{types-BtY5XChg.d.ts → types-CrLD4iRS.d.ts} +1 -1
  52. package/dist/{update-MFOCAROI.js → update-KDMUVXXI.js} +2 -2
  53. package/dist/web/assets/{index-DfmXvFVe.css → index-CsWZt1m8.css} +1 -1
  54. package/dist/web/assets/index-mJ_RQ-yF.js +305 -0
  55. package/dist/web/index.html +2 -2
  56. package/dist/web/sw.js +1 -1
  57. package/dist/{workspace-N2PIBOJV.js → workspace-MMV6V5P4.js} +4 -2
  58. package/package.json +1 -1
  59. package/dist/chunk-2X3V4SQC.js +0 -7
  60. package/dist/web/assets/index-C9jXZWzN.js +0 -305
@@ -8,7 +8,7 @@ import {
8
8
  spawnShellProcess,
9
9
  startProcessCommand,
10
10
  stopProcess
11
- } from "./chunk-JKZPMRH2.js";
11
+ } from "./chunk-3JYPDZT2.js";
12
12
  import {
13
13
  createMcpTools
14
14
  } from "./chunk-NWO6GRYE.js";
@@ -17,15 +17,16 @@ import {
17
17
  } from "./chunk-VPFUXGMM.js";
18
18
  import {
19
19
  getGitBranch,
20
+ isGitRepository,
20
21
  listWorkspaces
21
- } from "./chunk-JXTHW3YX.js";
22
+ } from "./chunk-7PZBCATU.js";
22
23
  import {
23
24
  PathAccessDeniedError,
24
25
  extractAbsolutePathsFromCommand,
25
26
  extractSensitivePathsFromCommand,
26
27
  registerPathConfirmation,
27
28
  requestPathAccess
28
- } from "./chunk-3D3N2PXI.js";
29
+ } from "./chunk-2KKFOVK7.js";
29
30
  import {
30
31
  createChatDoneMessage,
31
32
  createChatMessageMessage,
@@ -49,7 +50,7 @@ import {
49
50
  createToolCallEvent,
50
51
  createToolResultEvent,
51
52
  streamLLMPure
52
- } from "./chunk-FVY2JOTO.js";
53
+ } from "./chunk-H765CIHN.js";
53
54
  import {
54
55
  startInspectProxy
55
56
  } from "./chunk-EYIWUONA.js";
@@ -64,9 +65,8 @@ import {
64
65
  import {
65
66
  getCurrentContextWindowId,
66
67
  getCurrentWindowMessageOptions,
67
- getEventStore,
68
- getRuntimeConfig
69
- } from "./chunk-BUXIESO5.js";
68
+ getEventStore
69
+ } from "./chunk-V5LOH363.js";
70
70
  import {
71
71
  buildContextMessagesFromEventHistory,
72
72
  foldContextState,
@@ -76,7 +76,16 @@ import {
76
76
  handleToolResult,
77
77
  reorderToolMessages,
78
78
  stripOrphanedToolCalls
79
- } from "./chunk-A2IZ4PWQ.js";
79
+ } from "./chunk-OHKBGMLO.js";
80
+ import {
81
+ deleteItemFromDir,
82
+ findAgentById,
83
+ getRuntimeConfig,
84
+ getSubAgents,
85
+ loadAllAgentsDefault,
86
+ loadItemsFromDir,
87
+ pathExists
88
+ } from "./chunk-FYYPQ27K.js";
80
89
  import {
81
90
  modelSupportsVision
82
91
  } from "./chunk-V4IE7HJY.js";
@@ -96,14 +105,14 @@ import {
96
105
  deleteSetting,
97
106
  getSetting,
98
107
  setSetting
99
- } from "./chunk-CNJ63FXJ.js";
108
+ } from "./chunk-STFIEU5F.js";
100
109
  import {
101
110
  logger
102
111
  } from "./chunk-K44MW7JJ.js";
103
112
  import {
104
113
  loadGlobalConfig,
105
114
  saveGlobalConfig
106
- } from "./chunk-NH2PVB6R.js";
115
+ } from "./chunk-N54PQSCH.js";
107
116
  import {
108
117
  getGlobalConfigDir
109
118
  } from "./chunk-CQGTEGKL.js";
@@ -120,7 +129,7 @@ async function requestUserConfirmation(context, toolLabel, desc) {
120
129
  if (context.dangerLevel === "dangerous") return Promise.resolve(true);
121
130
  if (toolLabel === "workspace" || toolLabel === "command") {
122
131
  try {
123
- const { getSetting: getSetting2, SETTINGS_KEYS: SETTINGS_KEYS2 } = await import("./settings-6TJIHDVX.js");
132
+ const { getSetting: getSetting2, SETTINGS_KEYS: SETTINGS_KEYS2 } = await import("./settings-AGNYWEIE.js");
124
133
  if (getSetting2(SETTINGS_KEYS2.CONFIRM_ON_WORKSPACE_ACTIONS) !== "true") {
125
134
  return Promise.resolve(true);
126
135
  }
@@ -1468,283 +1477,13 @@ ${Object.entries(schema.fields).map(([f, t]) => ` ${f}: ${t}`).join("\n")}`
1468
1477
  );
1469
1478
 
1470
1479
  // src/server/sub-agents/manager.ts
1471
- import { readFile as readFile8, access as access5 } from "fs/promises";
1472
- import { join as join6, dirname as dirname5, isAbsolute as isAbsolute2 } from "path";
1473
-
1474
- // src/server/agents/registry.ts
1475
- import { readdir as readdir3, readFile as readFile5, writeFile as writeFile4, mkdir as mkdir3, access as access3, unlink as unlink2 } from "fs/promises";
1476
- import { join as join3, dirname as dirname2 } from "path";
1477
- import { constants as constants2 } from "fs";
1478
- import { fileURLToPath } from "url";
1479
- import matter2 from "gray-matter";
1480
-
1481
- // src/server/shared/item-loader.ts
1482
- import { readdir as readdir2, readFile as readFile4, access as access2, writeFile as writeFile3, mkdir as mkdir2, unlink } from "fs/promises";
1483
- import { join as join2 } from "path";
1484
- import { constants } from "fs";
1485
- import matter from "gray-matter";
1486
- async function pathExists(path) {
1487
- try {
1488
- await access2(path, constants.R_OK);
1489
- return true;
1490
- } catch {
1491
- return false;
1492
- }
1493
- }
1494
- async function getDefaultIds(dir, extension) {
1495
- try {
1496
- const files = (await readdir2(dir)).filter((f) => f.endsWith(extension));
1497
- return files.map((f) => f.replace(extension, ""));
1498
- } catch {
1499
- return [];
1500
- }
1501
- }
1502
- async function loadItemsFromDir(dir, options) {
1503
- if (!await pathExists(dir)) {
1504
- return [];
1505
- }
1506
- let files;
1507
- try {
1508
- files = (await readdir2(dir)).filter((f) => f.endsWith(options.extension));
1509
- } catch {
1510
- return [];
1511
- }
1512
- const items = [];
1513
- for (const file of files) {
1514
- try {
1515
- const raw = await readFile4(join2(dir, file), "utf-8");
1516
- const { data, content } = matter(raw);
1517
- if (data.id && content.trim()) {
1518
- items.push({
1519
- metadata: data,
1520
- prompt: content.trim()
1521
- });
1522
- } else {
1523
- logger.warn(`Skipping invalid ${options.logName} file`, { file });
1524
- }
1525
- } catch (err) {
1526
- logger.warn(`Failed to parse ${options.logName} file`, {
1527
- file,
1528
- error: err instanceof Error ? err.message : String(err)
1529
- });
1530
- }
1531
- }
1532
- return items;
1533
- }
1534
- async function saveItemToDir(dir, item, ext, serialize) {
1535
- if (!await pathExists(dir)) {
1536
- await mkdir2(dir, { recursive: true });
1537
- }
1538
- const meta = item.metadata;
1539
- const filePath = join2(dir, `${meta.id}${ext}`);
1540
- await writeFile3(filePath, serialize(item), "utf-8");
1541
- }
1542
- var jsonSerializer = (item) => JSON.stringify(item, null, 2) + "\n";
1543
- async function deleteItemFromDir(dir, id, ext) {
1544
- const filePath = join2(dir, `${id}${ext}`);
1545
- try {
1546
- await unlink(filePath);
1547
- return { success: true };
1548
- } catch {
1549
- return { success: false };
1550
- }
1551
- }
1552
-
1553
- // src/server/agents/registry.ts
1554
- var __bundleDir = dirname2(fileURLToPath(import.meta.url));
1555
- var DEFAULTS_DIR = join3(__bundleDir, "defaults");
1556
- var DEFAULTS_DIR_ALT = join3(__bundleDir, "agent-defaults");
1557
- var AGENT_EXTENSION = ".agent.md";
1558
- function getAgentsDir(configDir) {
1559
- return join3(configDir, "agents");
1560
- }
1561
- function getProjectAgentsDir(projectDir) {
1562
- return join3(projectDir, ".openfox", "agents");
1563
- }
1564
- async function pathExists2(path) {
1565
- try {
1566
- await access3(path, constants2.R_OK);
1567
- return true;
1568
- } catch {
1569
- return false;
1570
- }
1571
- }
1572
- function parseAgentFile(raw, filename) {
1573
- const { data, content } = matter2(raw);
1574
- const meta = data;
1575
- if (!meta["id"] || !content.trim()) {
1576
- logger.warn("Skipping invalid agent file", { filename });
1577
- return void 0;
1578
- }
1579
- const metadata = {
1580
- id: String(meta["id"]),
1581
- name: String(meta["name"] ?? meta["id"]),
1582
- description: String(meta["description"] ?? ""),
1583
- subagent: meta["subagent"] === true,
1584
- allowedTools: Array.isArray(meta["allowedTools"]) ? meta["allowedTools"].map(String) : [],
1585
- ...typeof meta["color"] === "string" ? { color: meta["color"] } : {},
1586
- ...Array.isArray(meta["results"]) ? { results: meta["results"].map(String) } : {}
1587
- };
1588
- return { metadata, prompt: content.trim() };
1589
- }
1590
- async function loadAgentsFromDir(dir) {
1591
- if (!await pathExists2(dir)) {
1592
- return [];
1593
- }
1594
- let files;
1595
- try {
1596
- files = (await readdir3(dir)).filter((f) => f.endsWith(AGENT_EXTENSION));
1597
- } catch {
1598
- return [];
1599
- }
1600
- const agents = [];
1601
- for (const file of files) {
1602
- try {
1603
- const raw = await readFile5(join3(dir, file), "utf-8");
1604
- const agent = parseAgentFile(raw, file);
1605
- if (agent) {
1606
- agents.push(agent);
1607
- }
1608
- } catch (err) {
1609
- logger.warn("Failed to parse agent file", { file, error: err instanceof Error ? err.message : String(err) });
1610
- }
1611
- }
1612
- return agents;
1613
- }
1614
- async function loadDefaultAgents() {
1615
- const agents = await loadAgentsFromDir(DEFAULTS_DIR);
1616
- if (agents.length > 0) return agents;
1617
- return loadAgentsFromDir(DEFAULTS_DIR_ALT);
1618
- }
1619
- async function loadUserAgents(configDir) {
1620
- return loadAgentsFromDir(getAgentsDir(configDir));
1621
- }
1622
- async function loadProjectAgents(projectDir) {
1623
- return loadAgentsFromDir(getProjectAgentsDir(projectDir));
1624
- }
1625
- async function loadAllAgents(configDir, projectDir) {
1626
- const [defaultAgents, userAgents] = await Promise.all([loadDefaultAgents(), loadUserAgents(configDir)]);
1627
- const agentMap = /* @__PURE__ */ new Map();
1628
- for (const agent of defaultAgents) {
1629
- agentMap.set(agent.metadata.id, agent);
1630
- }
1631
- for (const agent of userAgents) {
1632
- agentMap.set(agent.metadata.id, agent);
1633
- }
1634
- if (projectDir) {
1635
- const projectAgents = await loadProjectAgents(projectDir);
1636
- for (const agent of projectAgents) {
1637
- agentMap.set(agent.metadata.id, agent);
1638
- }
1639
- }
1640
- return Array.from(agentMap.values());
1641
- }
1642
- async function saveAgentToProject(projectDir, agent) {
1643
- await saveItemToDir(
1644
- getProjectAgentsDir(projectDir),
1645
- agent,
1646
- AGENT_EXTENSION,
1647
- (a) => matter2.stringify(a.prompt, a.metadata)
1648
- );
1649
- }
1650
- async function deleteProjectAgent(projectDir, agentId) {
1651
- const agentsDir = getProjectAgentsDir(projectDir);
1652
- const paths = getAgentFilePaths(agentsDir, agentId);
1653
- for (const filePath of paths) {
1654
- try {
1655
- await unlink2(filePath);
1656
- return { success: true };
1657
- } catch {
1658
- continue;
1659
- }
1660
- }
1661
- return { success: false };
1662
- }
1663
- async function loadAllAgentsDefault() {
1664
- try {
1665
- const config = getRuntimeConfig();
1666
- const configDir = getGlobalConfigDir(config.mode ?? "production");
1667
- return await loadAllAgents(configDir, config.workdir);
1668
- } catch {
1669
- return loadDefaultAgents();
1670
- }
1671
- }
1672
- async function getDefaultAgentIds() {
1673
- for (const dir of [DEFAULTS_DIR, DEFAULTS_DIR_ALT]) {
1674
- try {
1675
- const files = (await readdir3(dir)).filter((f) => f.endsWith(AGENT_EXTENSION));
1676
- return files.map((f) => f.replace(AGENT_EXTENSION, ""));
1677
- } catch {
1678
- }
1679
- }
1680
- return [];
1681
- }
1682
- async function isDefaultAgent(agentId) {
1683
- const defaultIds = await getDefaultAgentIds();
1684
- return defaultIds.includes(agentId);
1685
- }
1686
- function getAgentFilePaths(agentsDir, agentId) {
1687
- const hyphenated = agentId.replace(/_/g, "-");
1688
- return [join3(agentsDir, `${agentId}${AGENT_EXTENSION}`), join3(agentsDir, `${hyphenated}${AGENT_EXTENSION}`)];
1689
- }
1690
- function findAgentById(agentId, agents) {
1691
- return agents.find((a) => a.metadata.id === agentId);
1692
- }
1693
- function getSubAgents(agents) {
1694
- return agents.filter((a) => a.metadata.subagent);
1695
- }
1696
- function getTopLevelAgents(agents) {
1697
- return agents.filter((a) => !a.metadata.subagent);
1698
- }
1699
- async function agentExists(configDir, agentId, projectDir) {
1700
- const agentsDir = getAgentsDir(configDir);
1701
- const paths = getAgentFilePaths(agentsDir, agentId);
1702
- for (const filePath of paths) {
1703
- if (await pathExists2(filePath)) {
1704
- return true;
1705
- }
1706
- }
1707
- if (projectDir) {
1708
- const projectPaths = getAgentFilePaths(getProjectAgentsDir(projectDir), agentId);
1709
- for (const filePath of projectPaths) {
1710
- if (await pathExists2(filePath)) {
1711
- return true;
1712
- }
1713
- }
1714
- }
1715
- return false;
1716
- }
1717
- async function saveAgent(configDir, agent) {
1718
- const agentsDir = getAgentsDir(configDir);
1719
- if (!await pathExists2(agentsDir)) {
1720
- await mkdir3(agentsDir, { recursive: true });
1721
- }
1722
- const filePath = join3(agentsDir, `${agent.metadata.id}${AGENT_EXTENSION}`);
1723
- const content = matter2.stringify(agent.prompt, agent.metadata);
1724
- await writeFile4(filePath, content, "utf-8");
1725
- }
1726
- async function deleteAgent(configDir, agentId) {
1727
- const isDefault = await isDefaultAgent(agentId);
1728
- if (isDefault) {
1729
- return { success: false, reason: "Cannot delete built-in defaults" };
1730
- }
1731
- const agentsDir = getAgentsDir(configDir);
1732
- const paths = getAgentFilePaths(agentsDir, agentId);
1733
- for (const filePath of paths) {
1734
- try {
1735
- await unlink2(filePath);
1736
- return { success: true };
1737
- } catch {
1738
- continue;
1739
- }
1740
- }
1741
- return { success: false };
1742
- }
1480
+ import { readFile as readFile6, access as access3 } from "fs/promises";
1481
+ import { join as join4, dirname as dirname4, isAbsolute as isAbsolute2 } from "path";
1743
1482
 
1744
1483
  // src/server/context/instructions.ts
1745
- import { readFile as readFile6, access as access4 } from "fs/promises";
1746
- import { join as join4, dirname as dirname3 } from "path";
1747
- import { constants as constants3 } from "fs";
1484
+ import { readFile as readFile4, access as access2 } from "fs/promises";
1485
+ import { join as join2, dirname as dirname2 } from "path";
1486
+ import { constants } from "fs";
1748
1487
  var INSTRUCTION_FILENAMES = ["AGENTS.md", "CLAUDE.md"];
1749
1488
  async function findInstructionFiles(workdir) {
1750
1489
  const foundFiles = [];
@@ -1752,7 +1491,7 @@ async function findInstructionFiles(workdir) {
1752
1491
  let currentDir = workdir;
1753
1492
  while (true) {
1754
1493
  pathsToCheck.unshift(currentDir);
1755
- const parentDir = dirname3(currentDir);
1494
+ const parentDir = dirname2(currentDir);
1756
1495
  if (parentDir === currentDir) {
1757
1496
  break;
1758
1497
  }
@@ -1760,7 +1499,7 @@ async function findInstructionFiles(workdir) {
1760
1499
  }
1761
1500
  for (const dir of pathsToCheck) {
1762
1501
  for (const filename of INSTRUCTION_FILENAMES) {
1763
- const filePath = join4(dir, filename);
1502
+ const filePath = join2(dir, filename);
1764
1503
  if (await fileExists(filePath)) {
1765
1504
  foundFiles.push({
1766
1505
  path: filePath,
@@ -1775,7 +1514,7 @@ async function loadInstructions(files) {
1775
1514
  const contents = [];
1776
1515
  for (const file of files) {
1777
1516
  try {
1778
- const content = await readFile6(file.path, "utf-8");
1517
+ const content = await readFile4(file.path, "utf-8");
1779
1518
  contents.push(`Instructions from: ${file.path}
1780
1519
  ${content}`);
1781
1520
  } catch {
@@ -1810,7 +1549,7 @@ ${project.customInstructions}`);
1810
1549
  ${agentContent}`);
1811
1550
  for (const file of agentFiles) {
1812
1551
  try {
1813
- const content = await readFile6(file.path, "utf-8");
1552
+ const content = await readFile4(file.path, "utf-8");
1814
1553
  allFiles.push({ ...file, content });
1815
1554
  } catch {
1816
1555
  allFiles.push(file);
@@ -1825,7 +1564,7 @@ ${agentContent}`);
1825
1564
  }
1826
1565
  async function fileExists(path) {
1827
1566
  try {
1828
- await access4(path, constants3.R_OK);
1567
+ await access2(path, constants.R_OK);
1829
1568
  return true;
1830
1569
  } catch {
1831
1570
  return false;
@@ -1833,22 +1572,22 @@ async function fileExists(path) {
1833
1572
  }
1834
1573
 
1835
1574
  // src/server/skills/registry.ts
1836
- import { writeFile as writeFile5, mkdir as mkdir4, unlink as unlink3, readdir as readdir4, readFile as readFile7, realpath, rm } from "fs/promises";
1837
- import { join as join5, dirname as dirname4 } from "path";
1838
- import { fileURLToPath as fileURLToPath2 } from "url";
1575
+ import { writeFile as writeFile3, mkdir as mkdir2, unlink, readdir as readdir2, readFile as readFile5, realpath, rm } from "fs/promises";
1576
+ import { join as join3, dirname as dirname3 } from "path";
1577
+ import { fileURLToPath } from "url";
1839
1578
  import { homedir } from "os";
1840
- import matter3 from "gray-matter";
1841
- var __bundleDir2 = dirname4(fileURLToPath2(import.meta.url));
1842
- var DEFAULTS_DIR2 = join5(__bundleDir2, "defaults");
1843
- var DEFAULTS_DIR_ALT2 = join5(__bundleDir2, "skill-defaults");
1579
+ import matter from "gray-matter";
1580
+ var __bundleDir = dirname3(fileURLToPath(import.meta.url));
1581
+ var DEFAULTS_DIR = join3(__bundleDir, "defaults");
1582
+ var DEFAULTS_DIR_ALT = join3(__bundleDir, "skill-defaults");
1844
1583
  var SKILL_EXTENSION = ".skill.md";
1845
1584
  var SKILL_SETTING_PREFIX = "skill.enabled.";
1846
1585
  var PORTABLE_NAME_REGEX = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
1847
1586
  function getSkillsDir(configDir) {
1848
- return join5(configDir, "skills");
1587
+ return join3(configDir, "skills");
1849
1588
  }
1850
1589
  function getProjectSkillsDir(projectDir) {
1851
- return join5(projectDir, ".openfox", "skills");
1590
+ return join3(projectDir, ".openfox", "skills");
1852
1591
  }
1853
1592
  function portableDisplayName(data, id) {
1854
1593
  const metadata = data["metadata"];
@@ -1869,18 +1608,18 @@ function portableVersion(data) {
1869
1608
  async function loadPortableSkills(dir, source) {
1870
1609
  let entries;
1871
1610
  try {
1872
- entries = await readdir4(dir, { withFileTypes: true });
1611
+ entries = await readdir2(dir, { withFileTypes: true });
1873
1612
  } catch {
1874
1613
  return [];
1875
1614
  }
1876
1615
  const skills = [];
1877
1616
  for (const entry of entries) {
1878
1617
  if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;
1879
- const packageDir = join5(dir, entry.name);
1880
- const entrypoint = join5(packageDir, "SKILL.md");
1618
+ const packageDir = join3(dir, entry.name);
1619
+ const entrypoint = join3(packageDir, "SKILL.md");
1881
1620
  try {
1882
- const content = await readFile7(entrypoint, "utf-8");
1883
- const parsed = matter3(content);
1621
+ const content = await readFile5(entrypoint, "utf-8");
1622
+ const parsed = matter(content);
1884
1623
  const data = parsed.data;
1885
1624
  const id = typeof data["name"] === "string" ? data["name"].trim() : "";
1886
1625
  const description = typeof data["description"] === "string" ? data["description"].trim() : "";
@@ -1917,7 +1656,7 @@ async function loadPortableSkills(dir, source) {
1917
1656
  async function annotateLegacySkills(skills, dir, source) {
1918
1657
  return Promise.all(
1919
1658
  skills.map(async (skill) => {
1920
- const entrypoint = join5(dir, `${skill.metadata.id}${SKILL_EXTENSION}`);
1659
+ const entrypoint = join3(dir, `${skill.metadata.id}${SKILL_EXTENSION}`);
1921
1660
  let resolvedEntrypoint = entrypoint;
1922
1661
  try {
1923
1662
  resolvedEntrypoint = await realpath(entrypoint);
@@ -1927,7 +1666,7 @@ async function annotateLegacySkills(skills, dir, source) {
1927
1666
  ...skill,
1928
1667
  rawMetadata: { ...skill.metadata },
1929
1668
  entrypoint: resolvedEntrypoint,
1930
- directory: dirname4(resolvedEntrypoint),
1669
+ directory: dirname3(resolvedEntrypoint),
1931
1670
  source,
1932
1671
  legacy: true,
1933
1672
  warnings: ["Legacy .skill.md format"]
@@ -1956,9 +1695,9 @@ function getSelectedSkillDirectories() {
1956
1695
  }
1957
1696
  }
1958
1697
  async function loadDefaultSkills() {
1959
- const defaults = await loadSkillsDirectory(DEFAULTS_DIR2, "bundled");
1698
+ const defaults = await loadSkillsDirectory(DEFAULTS_DIR, "bundled");
1960
1699
  if (defaults.length) return defaults;
1961
- return loadSkillsDirectory(DEFAULTS_DIR_ALT2, "bundled");
1700
+ return loadSkillsDirectory(DEFAULTS_DIR_ALT, "bundled");
1962
1701
  }
1963
1702
  async function loadUserSkills(configDir) {
1964
1703
  return loadSkillsDirectory(getSkillsDir(configDir), "global-openfox");
@@ -1972,14 +1711,14 @@ async function loadAllSkills(configDir, projectDir, options = {}) {
1972
1711
  async function loadAllSkillsWithDiagnostics(configDir, projectDir, options = {}) {
1973
1712
  const home = options.homeDir ?? homedir();
1974
1713
  const selected = (options.selectedDirectories ?? getSelectedSkillDirectories()).map(
1975
- (dir) => dir === "~" ? home : dir.startsWith("~/") ? join5(home, dir.slice(2)) : dir
1714
+ (dir) => dir === "~" ? home : dir.startsWith("~/") ? join3(home, dir.slice(2)) : dir
1976
1715
  );
1977
1716
  const locations = [
1978
1717
  loadDefaultSkills(),
1979
- loadSkillsDirectory(join5(home, ".agents", "skills"), "global-shared"),
1718
+ loadSkillsDirectory(join3(home, ".agents", "skills"), "global-shared"),
1980
1719
  loadUserSkills(configDir),
1981
1720
  ...selected.map((dir) => loadSkillsDirectory(dir, "selected")),
1982
- ...projectDir ? [loadSkillsDirectory(join5(projectDir, ".agents", "skills"), "project-shared"), loadProjectSkills(projectDir)] : []
1721
+ ...projectDir ? [loadSkillsDirectory(join3(projectDir, ".agents", "skills"), "project-shared"), loadProjectSkills(projectDir)] : []
1983
1722
  ];
1984
1723
  const groups = await Promise.all(locations);
1985
1724
  const skillMap = /* @__PURE__ */ new Map();
@@ -2029,11 +1768,11 @@ function findSkillById(skillId, skills) {
2029
1768
  return skills.find((s) => s.metadata.id === skillId);
2030
1769
  }
2031
1770
  async function skillExists(configDir, skillId, projectDir) {
2032
- if (await pathExists(join5(getSkillsDir(configDir), `${skillId}${SKILL_EXTENSION}`))) return true;
2033
- if (await pathExists(join5(getSkillsDir(configDir), skillId, "SKILL.md"))) return true;
2034
- if (projectDir && await pathExists(join5(getProjectSkillsDir(projectDir), `${skillId}${SKILL_EXTENSION}`)))
1771
+ if (await pathExists(join3(getSkillsDir(configDir), `${skillId}${SKILL_EXTENSION}`))) return true;
1772
+ if (await pathExists(join3(getSkillsDir(configDir), skillId, "SKILL.md"))) return true;
1773
+ if (projectDir && await pathExists(join3(getProjectSkillsDir(projectDir), `${skillId}${SKILL_EXTENSION}`)))
2035
1774
  return true;
2036
- if (projectDir && await pathExists(join5(getProjectSkillsDir(projectDir), skillId, "SKILL.md"))) return true;
1775
+ if (projectDir && await pathExists(join3(getProjectSkillsDir(projectDir), skillId, "SKILL.md"))) return true;
2037
1776
  return false;
2038
1777
  }
2039
1778
  function portableFrontmatter(skill) {
@@ -2049,9 +1788,9 @@ function portableFrontmatter(skill) {
2049
1788
  };
2050
1789
  }
2051
1790
  async function savePortableSkill(dir, skill) {
2052
- const packageDir = join5(dir, skill.metadata.id);
2053
- await mkdir4(packageDir, { recursive: true });
2054
- await writeFile5(join5(packageDir, "SKILL.md"), matter3.stringify(skill.prompt, portableFrontmatter(skill)), "utf-8");
1791
+ const packageDir = join3(dir, skill.metadata.id);
1792
+ await mkdir2(packageDir, { recursive: true });
1793
+ await writeFile3(join3(packageDir, "SKILL.md"), matter.stringify(skill.prompt, portableFrontmatter(skill)), "utf-8");
2055
1794
  }
2056
1795
  async function saveSkill(configDir, skill) {
2057
1796
  await savePortableSkill(getSkillsDir(configDir), skill);
@@ -2098,7 +1837,7 @@ async function updateOwnedSkill(existing, changes) {
2098
1837
  rawMetadata: frontmatter,
2099
1838
  prompt: changes.prompt ?? existing.prompt
2100
1839
  };
2101
- await writeFile5(existing.entrypoint, matter3.stringify(updated2.prompt, frontmatter), "utf-8");
1840
+ await writeFile3(existing.entrypoint, matter.stringify(updated2.prompt, frontmatter), "utf-8");
2102
1841
  return updated2;
2103
1842
  }
2104
1843
  const metadata = {
@@ -2113,7 +1852,7 @@ async function updateOwnedSkill(existing, changes) {
2113
1852
  rawMetadata: metadata,
2114
1853
  prompt: changes.prompt ?? existing.prompt
2115
1854
  };
2116
- await writeFile5(existing.entrypoint, matter3.stringify(updated.prompt, metadata), "utf-8");
1855
+ await writeFile3(existing.entrypoint, matter.stringify(updated.prompt, metadata), "utf-8");
2117
1856
  return updated;
2118
1857
  }
2119
1858
  async function deleteOwnedSkill(existing) {
@@ -2121,8 +1860,8 @@ async function deleteOwnedSkill(existing) {
2121
1860
  return { success: false, reason: "This skill is read-only" };
2122
1861
  }
2123
1862
  try {
2124
- if (existing.legacy) await unlink3(existing.entrypoint);
2125
- else await rm(dirname4(existing.entrypoint), { recursive: true });
1863
+ if (existing.legacy) await unlink(existing.entrypoint);
1864
+ else await rm(dirname3(existing.entrypoint), { recursive: true });
2126
1865
  deleteSetting(`${SKILL_SETTING_PREFIX}${existing.metadata.id}`);
2127
1866
  return { success: true };
2128
1867
  } catch {
@@ -2134,9 +1873,9 @@ async function deleteSkill(configDir, skillId) {
2134
1873
  if (isDefault) {
2135
1874
  return { success: false, reason: "Cannot delete built-in defaults" };
2136
1875
  }
2137
- const filePath = join5(getSkillsDir(configDir), `${skillId}${SKILL_EXTENSION}`);
1876
+ const filePath = join3(getSkillsDir(configDir), `${skillId}${SKILL_EXTENSION}`);
2138
1877
  try {
2139
- await unlink3(filePath);
1878
+ await unlink(filePath);
2140
1879
  deleteSetting(`${SKILL_SETTING_PREFIX}${skillId}`);
2141
1880
  return { success: true };
2142
1881
  } catch {
@@ -2576,7 +2315,7 @@ ${CONTINUE_PROMPT}` : CONTINUE_PROMPT;
2576
2315
  sessionManager.setCurrentContextSize(sessionId, result.usage.promptTokens, config.subAgentMetadata?.subAgentId);
2577
2316
  if (!compacting) {
2578
2317
  const contextState2 = sessionManager.getContextState(sessionId);
2579
- const { shouldCompact, appendCompactionPrompt } = await import("./compactor-YKESKGHL.js");
2318
+ const { shouldCompact, appendCompactionPrompt } = await import("./compactor-2YT66FDZ.js");
2580
2319
  if (shouldCompact(
2581
2320
  contextState2.currentTokens,
2582
2321
  contextState2.maxTokens,
@@ -2939,7 +2678,7 @@ async function describeImageFromDataUrl(dataUrl, visionModel, options) {
2939
2678
  // src/server/context/image-processor.ts
2940
2679
  async function loadVisionModelFromGlobalConfig() {
2941
2680
  try {
2942
- const { loadGlobalConfig: loadGlobalConfig2, getVisionFallback } = await import("./config-EN3WEH4A.js");
2681
+ const { loadGlobalConfig: loadGlobalConfig2, getVisionFallback } = await import("./config-JN6MW5SL.js");
2943
2682
  const runtimeConfig = getRuntimeConfig();
2944
2683
  const mode = runtimeConfig.mode ?? "production";
2945
2684
  const globalConfig = await loadGlobalConfig2(mode);
@@ -3310,10 +3049,10 @@ async function loadGitIgnoreRules(workdir) {
3310
3049
  if (!isAbsolute2(workdir)) return "";
3311
3050
  let currentDir = workdir;
3312
3051
  while (true) {
3313
- const gitignorePath = join6(currentDir, ".gitignore");
3052
+ const gitignorePath = join4(currentDir, ".gitignore");
3314
3053
  try {
3315
- await access5(gitignorePath);
3316
- const content = await readFile8(gitignorePath, "utf-8");
3054
+ await access3(gitignorePath);
3055
+ const content = await readFile6(gitignorePath, "utf-8");
3317
3056
  const trimmed = content.trim();
3318
3057
  if (!trimmed) return "";
3319
3058
  const lines = trimmed.split("\n");
@@ -3327,7 +3066,7 @@ The following patterns from \`.gitignore\` should be excluded from file searches
3327
3066
  ${final}`;
3328
3067
  } catch {
3329
3068
  }
3330
- const parentDir = dirname5(currentDir);
3069
+ const parentDir = dirname4(currentDir);
3331
3070
  if (parentDir === currentDir) break;
3332
3071
  currentDir = parentDir;
3333
3072
  }
@@ -3515,7 +3254,7 @@ var callSubAgentTool = {
3515
3254
  };
3516
3255
  }
3517
3256
  try {
3518
- const { getToolRegistryForAgent: getToolRegistryForAgent2 } = await import("./tools-X4YLRR2Y.js");
3257
+ const { getToolRegistryForAgent: getToolRegistryForAgent2 } = await import("./tools-ZUTPBREL.js");
3519
3258
  const toolRegistry = getToolRegistryForAgent2(agentDef);
3520
3259
  const turnMetrics = new TurnMetrics();
3521
3260
  const result = await executeSubAgent({
@@ -3800,8 +3539,8 @@ var webFetchTool = createTool(
3800
3539
 
3801
3540
  // src/server/dev-server/manager.ts
3802
3541
  import "child_process";
3803
- import { readFile as readFile9, writeFile as writeFile6, mkdir as mkdir5 } from "fs/promises";
3804
- import { resolve as resolve4, join as join7 } from "path";
3542
+ import { readFile as readFile7, writeFile as writeFile4, mkdir as mkdir3 } from "fs/promises";
3543
+ import { resolve as resolve4, join as join5 } from "path";
3805
3544
  import net from "net";
3806
3545
  var MAX_LOG_LINES = 2e3;
3807
3546
  var MAX_LOG_BYTES = 1e5;
@@ -3809,7 +3548,7 @@ var DEFAULT_PROBE_PORT = 10469;
3809
3548
  var MAX_PORT_SCAN = 200;
3810
3549
  var PROBE_TIMEOUT_MS = 300;
3811
3550
  var getDevServerConfigPath = (workdir) => {
3812
- return join7(resolve4(workdir), ".openfox", "dev.json");
3551
+ return join5(resolve4(workdir), ".openfox", "dev.json");
3813
3552
  };
3814
3553
  var ERROR_PATTERNS = [
3815
3554
  /EADDRINUSE/,
@@ -3930,7 +3669,7 @@ var DevServerManager = class {
3930
3669
  const tryLoad = async (dir) => {
3931
3670
  try {
3932
3671
  const configPath = getDevServerConfigPath(dir);
3933
- const raw = await readFile9(configPath, "utf-8");
3672
+ const raw = await readFile7(configPath, "utf-8");
3934
3673
  const parsed = JSON.parse(raw);
3935
3674
  if (!parsed.command || !parsed.url) return null;
3936
3675
  return {
@@ -3956,10 +3695,10 @@ var DevServerManager = class {
3956
3695
  }
3957
3696
  async saveConfig(workdir, config) {
3958
3697
  const resolved = this.resolveWorkdir(workdir);
3959
- const dirPath = join7(resolved, ".openfox");
3960
- await mkdir5(dirPath, { recursive: true });
3698
+ const dirPath = join5(resolved, ".openfox");
3699
+ await mkdir3(dirPath, { recursive: true });
3961
3700
  const configPath = getDevServerConfigPath(workdir);
3962
- await writeFile6(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
3701
+ await writeFile4(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
3963
3702
  }
3964
3703
  async start(workdir) {
3965
3704
  const instance = this.getInstance(workdir);
@@ -4518,7 +4257,7 @@ var mcpConfigTool = createTool(
4518
4257
  mcpNotifyChanged?.(sessionId);
4519
4258
  }
4520
4259
  async function rebuildTools() {
4521
- const { setMcpTools: setMcpTools2 } = await import("./tools-X4YLRR2Y.js");
4260
+ const { setMcpTools: setMcpTools2 } = await import("./tools-ZUTPBREL.js");
4522
4261
  const mcpTools = createMcpTools(mcpManagerForTools);
4523
4262
  setMcpTools2(mcpTools);
4524
4263
  }
@@ -4797,7 +4536,7 @@ var workspaceTool = createTool(
4797
4536
  type: "function",
4798
4537
  function: {
4799
4538
  name: "workspace",
4800
- description: 'Manage workspaces for the current session. A workspace is a cloned copy of the project.\n\nUse "switch" to move between workspaces. Target "original" for the project root, or a workspace name.\nIf the workspace does not exist yet, it is created automatically.\n\nYou can also change the branch of the current workspace by calling switch with the current\nworkspace name and a branch parameter. The branch will be checked out without recreating\nthe workspace and without losing uncommitted changes.\n\nIf the requested branch does not exist, it will be created. By default it is based on the\ndefault branch of the project (origin/HEAD). You can specify sourceBranch to base the new\nbranch on a different existing branch.\n\nActions that change the workspace (switch, delete) require explicit user approval via a confirmation dialog.\n\nSetup commands (e.g. npm install) are configured via .openfox/workspace.json.\n\nActions:\n- switch: Switch to a workspace (target: "original" or a name, optional branch for new workspaces)\n- list: List all workspaces with their current branch and active status\n- delete: Delete a workspace by name (cannot delete "original")',
4539
+ description: 'Manage workspaces for the current session. A workspace is a cloned copy of the project.\n\nUse "switch" to move between workspaces. Target "original" for the project root, or a workspace name.\nIf the workspace does not exist yet, it is created automatically.\n\nYou can also change the branch of the current workspace by calling switch with the current\nworkspace name and a branch parameter. The branch will be checked out without recreating\nthe workspace and without losing uncommitted changes.\n\nIf the requested branch does not exist, it will be created. By default it is based on the\ndefault branch of the project (origin/HEAD). You can specify sourceBranch to base the new\nbranch on a different existing branch.\n\nActions that change the workspace (switch, delete) require explicit user approval via a confirmation dialog.\n\nSetup commands (e.g. npm install) are configured via .openfox/workspace.json.\n\nActions:\n- switch: Switch to a workspace (target: "original" or a name, optional branch for new workspaces)\n- list: List all workspaces with their current branch and active status\n- delete: Delete a workspace by name (cannot delete "original"). Use force=true to auto-switch other sessions that reference this workspace.',
4801
4540
  parameters: {
4802
4541
  type: "object",
4803
4542
  properties: {
@@ -4817,6 +4556,10 @@ var workspaceTool = createTool(
4817
4556
  sourceBranch: {
4818
4557
  type: "string",
4819
4558
  description: "If branch does not exist, base the new branch on this existing branch. Default: origin/HEAD."
4559
+ },
4560
+ force: {
4561
+ type: "boolean",
4562
+ description: "For action=delete: force deletion by auto-switching other sessions that reference this workspace to original first."
4820
4563
  }
4821
4564
  },
4822
4565
  required: ["action"]
@@ -4834,6 +4577,9 @@ var workspaceTool = createTool(
4834
4577
  if (!args.target || typeof args.target !== "string") {
4835
4578
  return helpers.error('Parameter "target" is required for action=switch ("original" or a workspace name)');
4836
4579
  }
4580
+ if (await isGitRepository(context.workdir) === false) {
4581
+ return helpers.error("Project is not a git repository");
4582
+ }
4837
4583
  const currentSession = sessionManager.getSession(sessionId);
4838
4584
  const isBranchChange = args.branch !== void 0 && currentSession != null && args.target !== "original" && currentSession.workspace?.split("/").pop() === args.target;
4839
4585
  const label = args.target === "original" ? "original project" : `workspace "${args.target}"`;
@@ -4879,9 +4625,17 @@ var workspaceTool = createTool(
4879
4625
  return helpers.error('Parameter "target" is required for action=delete (the workspace name)');
4880
4626
  }
4881
4627
  if (args.target === "original") return helpers.error("Cannot delete the original workspace");
4882
- const approved = await requestUserConfirmation(context, "workspace", `Delete workspace "${args.target}"`);
4628
+ if (await isGitRepository(context.workdir) === false) {
4629
+ return helpers.error("Project is not a git repository");
4630
+ }
4631
+ const forceDesc = args.force ? " (will auto-switch other sessions to original)" : "";
4632
+ const approved = await requestUserConfirmation(
4633
+ context,
4634
+ "workspace",
4635
+ `Delete workspace "${args.target}"${forceDesc}`
4636
+ );
4883
4637
  if (!approved) return helpers.error(`User denied: delete workspace "${args.target}"`);
4884
- await sessionManager.deleteWorkspace(sessionId, args.target);
4638
+ await sessionManager.deleteWorkspace(sessionId, args.target, args.force === true);
4885
4639
  return helpers.success(
4886
4640
  JSON.stringify(
4887
4641
  {
@@ -5121,27 +4875,6 @@ function createToolRegistry() {
5121
4875
  }
5122
4876
 
5123
4877
  export {
5124
- pathExists,
5125
- getDefaultIds,
5126
- loadItemsFromDir,
5127
- saveItemToDir,
5128
- jsonSerializer,
5129
- deleteItemFromDir,
5130
- loadDefaultAgents,
5131
- loadUserAgents,
5132
- loadProjectAgents,
5133
- loadAllAgents,
5134
- saveAgentToProject,
5135
- deleteProjectAgent,
5136
- loadAllAgentsDefault,
5137
- getDefaultAgentIds,
5138
- isDefaultAgent,
5139
- findAgentById,
5140
- getSubAgents,
5141
- getTopLevelAgents,
5142
- agentExists,
5143
- saveAgent,
5144
- deleteAgent,
5145
4878
  getAllInstructions,
5146
4879
  loadDefaultSkills,
5147
4880
  loadUserSkills,
@@ -5181,4 +4914,4 @@ export {
5181
4914
  getToolRegistryForAgent,
5182
4915
  createToolRegistry
5183
4916
  };
5184
- //# sourceMappingURL=chunk-OBQN5ATP.js.map
4917
+ //# sourceMappingURL=chunk-RSO2HKNH.js.map