openfox 2.0.58 → 2.0.60
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.
- package/dist/agent-defaults/explorer.agent.md +4 -0
- package/dist/{branch.api-5DMEAIBI.js → branch.api-LAN42BA5.js} +3 -2
- package/dist/{chat-handler-W5D5LKKU.js → chat-handler-MBR6ZQTX.js} +7 -7
- package/dist/{chunk-LAWUUAN7.js → chunk-3JRYK5UG.js} +323 -80
- package/dist/{chunk-YMEZFRY2.js → chunk-43UFGATL.js} +5 -5
- package/dist/{chunk-BIWVYBIE.js → chunk-BGTEIA2S.js} +4 -3
- package/dist/{chunk-UDZNMYWN.js → chunk-DEWNWF2P.js} +519 -280
- package/dist/{chunk-CFLGVCYT.js → chunk-DOJKA4XO.js} +20 -9
- package/dist/{chunk-55VITQP3.js → chunk-MTBQQ5DN.js} +9 -9
- package/dist/{chunk-XR2XC7WM.js → chunk-NY6IGGKZ.js} +3 -3
- package/dist/{chunk-ADOXTORQ.js → chunk-PK2RMVMB.js} +2 -2
- package/dist/{chunk-CDRQJDSJ.js → chunk-WNSAJCWT.js} +3 -2
- package/dist/cli/dev.js +2 -2
- package/dist/cli/index.js +2 -2
- package/dist/{config-C2YDEF3N.js → config-GMQUPNBY.js} +2 -2
- package/dist/{manager-CZOVNTSN.js → manager-344C5JLZ.js} +3 -3
- package/dist/{orchestrator-Q47D6JXG.js → orchestrator-PIZJ42J2.js} +7 -7
- package/dist/package.json +4 -2
- package/dist/{permissions-QLHZUEGW.js → permissions-CGEK3DGZ.js} +21 -17
- package/dist/{processor-2YJ33KUH.js → processor-PKKTNKWY.js} +7 -7
- package/dist/{project-creator-7RBHP6K6.js → project-creator-IDW7RACH.js} +4 -4
- package/dist/{protocol-PSKVUhdN.d.ts → protocol-J7khRG62.d.ts} +2 -0
- package/dist/{provider-SNXYPSPH.js → provider-LBYBC5AG.js} +3 -3
- package/dist/{pwa-M6QZ52ZO.js → pwa-T6JRAYJB.js} +11 -10
- package/dist/{serve-LOPGRMFP.js → serve-GKS55Y2C.js} +9 -9
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +8 -8
- package/dist/{server-XUDZRBD3.js → server-LMH7ZH5X.js} +8 -8
- package/dist/{service-YYJ5Y7CN.js → service-6DL3MJZD.js} +7 -5
- package/dist/{settings-X43DCM55.js → settings-2TQA7VTP.js} +2 -2
- package/dist/shared/index.d.ts +2 -2
- package/dist/skill-defaults/{browser.skill.md → browser/SKILL.md} +5 -3
- package/dist/{store-NS2RMRA7.js → store-FXTCHBI4.js} +2 -2
- package/dist/{tools-YJLXW3QS.js → tools-WGAZKL56.js} +6 -6
- package/dist/web/assets/index-C0YKw2cD.js +302 -0
- package/dist/web/assets/{index-DjfRXOO7.css → index-D4bVx84a.css} +1 -1
- package/dist/web/index.html +2 -2
- package/dist/web/sw.js +1 -1
- package/package.json +4 -2
- package/dist/web/assets/index-Dqqp_j-f.js +0 -302
|
@@ -9,12 +9,12 @@ import {
|
|
|
9
9
|
getSessionProcesses,
|
|
10
10
|
startProcessCommand,
|
|
11
11
|
stopProcess
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-BGTEIA2S.js";
|
|
13
13
|
import {
|
|
14
14
|
getMaxPerSession,
|
|
15
15
|
getSessionProcessCount,
|
|
16
16
|
terminateProcessTree
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-PK2RMVMB.js";
|
|
18
18
|
import {
|
|
19
19
|
createMcpTools
|
|
20
20
|
} from "./chunk-NWO6GRYE.js";
|
|
@@ -32,8 +32,9 @@ import {
|
|
|
32
32
|
import {
|
|
33
33
|
SETTINGS_KEYS,
|
|
34
34
|
deleteSetting,
|
|
35
|
-
getSetting
|
|
36
|
-
|
|
35
|
+
getSetting,
|
|
36
|
+
setSetting
|
|
37
|
+
} from "./chunk-WNSAJCWT.js";
|
|
37
38
|
import {
|
|
38
39
|
getProject
|
|
39
40
|
} from "./chunk-YQ3SOPBI.js";
|
|
@@ -73,7 +74,7 @@ import {
|
|
|
73
74
|
import {
|
|
74
75
|
loadGlobalConfig,
|
|
75
76
|
saveGlobalConfig
|
|
76
|
-
} from "./chunk-
|
|
77
|
+
} from "./chunk-43UFGATL.js";
|
|
77
78
|
import {
|
|
78
79
|
getGlobalConfigDir
|
|
79
80
|
} from "./chunk-CQGTEGKL.js";
|
|
@@ -222,6 +223,9 @@ async function isPathWithinSandbox(path, workdir, sessionId) {
|
|
|
222
223
|
function looksLikeRegex(str) {
|
|
223
224
|
return /[*?+[\]\\]/.test(str);
|
|
224
225
|
}
|
|
226
|
+
function isPlaceholderToken(str) {
|
|
227
|
+
return str.includes("__URL__") || str.includes("__FILEURL__") || str.includes("__SED__");
|
|
228
|
+
}
|
|
225
229
|
function extractAbsolutePathsFromCommand(command) {
|
|
226
230
|
if (!command.trim()) {
|
|
227
231
|
return [];
|
|
@@ -273,16 +277,13 @@ function extractAbsolutePathsFromCommand(command) {
|
|
|
273
277
|
}
|
|
274
278
|
}
|
|
275
279
|
}
|
|
276
|
-
const absolutePattern = /(?:^|[\s=(])(
|
|
280
|
+
const absolutePattern = /(?:^|[\s=(])(\/[^\s"'|&;<>`()]+)/g;
|
|
277
281
|
while ((match = absolutePattern.exec(sanitized)) !== null) {
|
|
278
|
-
const
|
|
279
|
-
if (
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
if (
|
|
283
|
-
continue;
|
|
284
|
-
}
|
|
285
|
-
const resolved = normalize(pathCandidate);
|
|
282
|
+
const candidate = match[1];
|
|
283
|
+
if (isPlaceholderToken(candidate)) continue;
|
|
284
|
+
if (looksLikeRegex(candidate)) continue;
|
|
285
|
+
const resolved = normalize(candidate);
|
|
286
|
+
if (resolved === "/" || resolved === "") continue;
|
|
286
287
|
if (!isSafePath(resolved)) {
|
|
287
288
|
paths.push(resolved);
|
|
288
289
|
}
|
|
@@ -1330,6 +1331,7 @@ function spawnShellProcess(command, cwd, _signal, detached = false) {
|
|
|
1330
1331
|
cwd,
|
|
1331
1332
|
env: { ...process.env, FORCE_COLOR: "0" },
|
|
1332
1333
|
stdio: ["ignore", "pipe", "pipe"],
|
|
1334
|
+
windowsHide: true,
|
|
1333
1335
|
...detached ? { detached: true } : {}
|
|
1334
1336
|
});
|
|
1335
1337
|
}
|
|
@@ -1667,6 +1669,10 @@ ${Object.entries(schema.fields).map(([f, t]) => ` ${f}: ${t}`).join("\n")}`
|
|
|
1667
1669
|
}
|
|
1668
1670
|
);
|
|
1669
1671
|
|
|
1672
|
+
// src/server/sub-agents/manager.ts
|
|
1673
|
+
import { readFile as readFile8, access as access4 } from "fs/promises";
|
|
1674
|
+
import { join as join7, dirname as dirname5, isAbsolute as isAbsolute3 } from "path";
|
|
1675
|
+
|
|
1670
1676
|
// src/server/agents/registry.ts
|
|
1671
1677
|
import { readdir as readdir3, readFile as readFile5, writeFile as writeFile4, mkdir as mkdir3, access as access2, unlink as unlink2 } from "fs/promises";
|
|
1672
1678
|
import { join as join4, dirname as dirname2 } from "path";
|
|
@@ -2029,62 +2035,173 @@ async function fileExists(path) {
|
|
|
2029
2035
|
}
|
|
2030
2036
|
|
|
2031
2037
|
// src/server/skills/registry.ts
|
|
2032
|
-
import { writeFile as writeFile5, mkdir as mkdir4, unlink as unlink3 } from "fs/promises";
|
|
2038
|
+
import { writeFile as writeFile5, mkdir as mkdir4, unlink as unlink3, readdir as readdir4, readFile as readFile7, realpath as realpath2, rm } from "fs/promises";
|
|
2033
2039
|
import { join as join6, dirname as dirname4 } from "path";
|
|
2034
2040
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
2041
|
+
import { homedir as homedir2 } from "os";
|
|
2035
2042
|
import matter3 from "gray-matter";
|
|
2036
2043
|
var __bundleDir2 = dirname4(fileURLToPath2(import.meta.url));
|
|
2037
2044
|
var DEFAULTS_DIR2 = join6(__bundleDir2, "defaults");
|
|
2038
2045
|
var DEFAULTS_DIR_ALT2 = join6(__bundleDir2, "skill-defaults");
|
|
2039
2046
|
var SKILL_EXTENSION = ".skill.md";
|
|
2040
2047
|
var SKILL_SETTING_PREFIX = "skill.enabled.";
|
|
2048
|
+
var PORTABLE_NAME_REGEX = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
2041
2049
|
function getSkillsDir(configDir) {
|
|
2042
2050
|
return join6(configDir, "skills");
|
|
2043
2051
|
}
|
|
2044
2052
|
function getProjectSkillsDir(projectDir) {
|
|
2045
2053
|
return join6(projectDir, ".openfox", "skills");
|
|
2046
2054
|
}
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2055
|
+
function portableDisplayName(data, id) {
|
|
2056
|
+
const metadata = data["metadata"];
|
|
2057
|
+
if (!metadata || typeof metadata !== "object" || Array.isArray(metadata)) return id;
|
|
2058
|
+
const openfox = metadata["openfox"];
|
|
2059
|
+
if (!openfox || typeof openfox !== "object" || Array.isArray(openfox)) return id;
|
|
2060
|
+
const displayName = openfox["displayName"];
|
|
2061
|
+
return typeof displayName === "string" && displayName.trim() ? displayName : id;
|
|
2062
|
+
}
|
|
2063
|
+
function portableVersion(data) {
|
|
2064
|
+
const metadata = data["metadata"];
|
|
2065
|
+
if (metadata && typeof metadata === "object" && !Array.isArray(metadata)) {
|
|
2066
|
+
const version = metadata["version"];
|
|
2067
|
+
if (version !== void 0) return String(version);
|
|
2057
2068
|
}
|
|
2058
|
-
return
|
|
2069
|
+
return data["version"] === void 0 ? "" : String(data["version"]);
|
|
2070
|
+
}
|
|
2071
|
+
async function loadPortableSkills(dir, source) {
|
|
2072
|
+
let entries;
|
|
2073
|
+
try {
|
|
2074
|
+
entries = await readdir4(dir, { withFileTypes: true });
|
|
2075
|
+
} catch {
|
|
2076
|
+
return [];
|
|
2077
|
+
}
|
|
2078
|
+
const skills = [];
|
|
2079
|
+
for (const entry of entries) {
|
|
2080
|
+
if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;
|
|
2081
|
+
const packageDir = join6(dir, entry.name);
|
|
2082
|
+
const entrypoint = join6(packageDir, "SKILL.md");
|
|
2083
|
+
try {
|
|
2084
|
+
const content = await readFile7(entrypoint, "utf-8");
|
|
2085
|
+
const parsed = matter3(content);
|
|
2086
|
+
const data = parsed.data;
|
|
2087
|
+
const id = typeof data["name"] === "string" ? data["name"].trim() : "";
|
|
2088
|
+
const description = typeof data["description"] === "string" ? data["description"].trim() : "";
|
|
2089
|
+
const prompt = parsed.content.trim();
|
|
2090
|
+
if (!id || !description || !prompt) continue;
|
|
2091
|
+
const resolvedDirectory = await realpath2(packageDir);
|
|
2092
|
+
const warnings = [];
|
|
2093
|
+
if (id.length > 64 || !PORTABLE_NAME_REGEX.test(id)) {
|
|
2094
|
+
warnings.push("Skill name must use 1-64 lowercase letters, numbers, and single hyphens");
|
|
2095
|
+
}
|
|
2096
|
+
if (id !== entry.name) {
|
|
2097
|
+
warnings.push(`Skill name "${id}" does not match package directory "${entry.name}"`);
|
|
2098
|
+
}
|
|
2099
|
+
skills.push({
|
|
2100
|
+
metadata: {
|
|
2101
|
+
id,
|
|
2102
|
+
name: portableDisplayName(data, id),
|
|
2103
|
+
description,
|
|
2104
|
+
version: portableVersion(data)
|
|
2105
|
+
},
|
|
2106
|
+
prompt,
|
|
2107
|
+
rawMetadata: data,
|
|
2108
|
+
entrypoint,
|
|
2109
|
+
directory: resolvedDirectory,
|
|
2110
|
+
source,
|
|
2111
|
+
legacy: false,
|
|
2112
|
+
warnings
|
|
2113
|
+
});
|
|
2114
|
+
} catch {
|
|
2115
|
+
}
|
|
2116
|
+
}
|
|
2117
|
+
return skills;
|
|
2118
|
+
}
|
|
2119
|
+
async function annotateLegacySkills(skills, dir, source) {
|
|
2120
|
+
return Promise.all(
|
|
2121
|
+
skills.map(async (skill) => {
|
|
2122
|
+
const entrypoint = join6(dir, `${skill.metadata.id}${SKILL_EXTENSION}`);
|
|
2123
|
+
let resolvedEntrypoint = entrypoint;
|
|
2124
|
+
try {
|
|
2125
|
+
resolvedEntrypoint = await realpath2(entrypoint);
|
|
2126
|
+
} catch {
|
|
2127
|
+
}
|
|
2128
|
+
return {
|
|
2129
|
+
...skill,
|
|
2130
|
+
rawMetadata: { ...skill.metadata },
|
|
2131
|
+
entrypoint: resolvedEntrypoint,
|
|
2132
|
+
directory: dirname4(resolvedEntrypoint),
|
|
2133
|
+
source,
|
|
2134
|
+
legacy: true,
|
|
2135
|
+
warnings: ["Legacy .skill.md format"]
|
|
2136
|
+
};
|
|
2137
|
+
})
|
|
2138
|
+
);
|
|
2139
|
+
}
|
|
2140
|
+
async function loadSkillsDirectory(dir, source) {
|
|
2141
|
+
const [legacyRaw, portable] = await Promise.all([
|
|
2142
|
+
loadItemsFromDir(dir, { extension: SKILL_EXTENSION, logName: "skill" }),
|
|
2143
|
+
loadPortableSkills(dir, source)
|
|
2144
|
+
]);
|
|
2145
|
+
const legacy = await annotateLegacySkills(legacyRaw, dir, source);
|
|
2146
|
+
const merged = new Map(legacy.map((skill) => [skill.metadata.id, skill]));
|
|
2147
|
+
for (const skill of portable) merged.set(skill.metadata.id, skill);
|
|
2148
|
+
return [...merged.values()];
|
|
2149
|
+
}
|
|
2150
|
+
function getSelectedSkillDirectories() {
|
|
2151
|
+
const raw = getSetting("skills.directories");
|
|
2152
|
+
if (!raw) return [];
|
|
2153
|
+
try {
|
|
2154
|
+
const parsed = JSON.parse(raw);
|
|
2155
|
+
return Array.isArray(parsed) ? parsed.filter((value) => typeof value === "string") : [];
|
|
2156
|
+
} catch {
|
|
2157
|
+
return [];
|
|
2158
|
+
}
|
|
2159
|
+
}
|
|
2160
|
+
async function loadDefaultSkills() {
|
|
2161
|
+
const defaults = await loadSkillsDirectory(DEFAULTS_DIR2, "bundled");
|
|
2162
|
+
if (defaults.length) return defaults;
|
|
2163
|
+
return loadSkillsDirectory(DEFAULTS_DIR_ALT2, "bundled");
|
|
2059
2164
|
}
|
|
2060
2165
|
async function loadUserSkills(configDir) {
|
|
2061
|
-
return
|
|
2062
|
-
extension: SKILL_EXTENSION,
|
|
2063
|
-
logName: "skill"
|
|
2064
|
-
});
|
|
2166
|
+
return loadSkillsDirectory(getSkillsDir(configDir), "global-openfox");
|
|
2065
2167
|
}
|
|
2066
2168
|
async function loadProjectSkills(projectDir) {
|
|
2067
|
-
return
|
|
2068
|
-
extension: SKILL_EXTENSION,
|
|
2069
|
-
logName: "skill"
|
|
2070
|
-
});
|
|
2169
|
+
return loadSkillsDirectory(getProjectSkillsDir(projectDir), "project-openfox");
|
|
2071
2170
|
}
|
|
2072
|
-
async function loadAllSkills(configDir, projectDir) {
|
|
2073
|
-
|
|
2171
|
+
async function loadAllSkills(configDir, projectDir, options = {}) {
|
|
2172
|
+
return (await loadAllSkillsWithDiagnostics(configDir, projectDir, options)).skills;
|
|
2173
|
+
}
|
|
2174
|
+
async function loadAllSkillsWithDiagnostics(configDir, projectDir, options = {}) {
|
|
2175
|
+
const home = options.homeDir ?? homedir2();
|
|
2176
|
+
const selected = (options.selectedDirectories ?? getSelectedSkillDirectories()).map(
|
|
2177
|
+
(dir) => dir === "~" ? home : dir.startsWith("~/") ? join6(home, dir.slice(2)) : dir
|
|
2178
|
+
);
|
|
2179
|
+
const locations = [
|
|
2180
|
+
loadDefaultSkills(),
|
|
2181
|
+
loadSkillsDirectory(join6(home, ".agents", "skills"), "global-shared"),
|
|
2182
|
+
loadUserSkills(configDir),
|
|
2183
|
+
...selected.map((dir) => loadSkillsDirectory(dir, "selected")),
|
|
2184
|
+
...projectDir ? [loadSkillsDirectory(join6(projectDir, ".agents", "skills"), "project-shared"), loadProjectSkills(projectDir)] : []
|
|
2185
|
+
];
|
|
2186
|
+
const groups = await Promise.all(locations);
|
|
2074
2187
|
const skillMap = /* @__PURE__ */ new Map();
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2188
|
+
const diagnostics = [];
|
|
2189
|
+
for (const group of groups) {
|
|
2190
|
+
for (const skill of group) {
|
|
2191
|
+
const previous = skillMap.get(skill.metadata.id);
|
|
2192
|
+
if (previous) {
|
|
2193
|
+
if (previous.directory === skill.directory && previous.legacy === skill.legacy) {
|
|
2194
|
+
diagnostics.push(`Skill "${skill.metadata.id}" reached through multiple paths`);
|
|
2195
|
+
} else {
|
|
2196
|
+
diagnostics.push(
|
|
2197
|
+
`Skill "${skill.metadata.id}" from ${skill.source ?? "unknown"} overrides ${previous.source ?? "unknown"}`
|
|
2198
|
+
);
|
|
2199
|
+
}
|
|
2200
|
+
}
|
|
2084
2201
|
skillMap.set(skill.metadata.id, skill);
|
|
2085
2202
|
}
|
|
2086
2203
|
}
|
|
2087
|
-
return Array.from(skillMap.values());
|
|
2204
|
+
return { skills: Array.from(skillMap.values()), diagnostics };
|
|
2088
2205
|
}
|
|
2089
2206
|
async function getEnabledSkills(configDir, projectDir) {
|
|
2090
2207
|
const all = await loadAllSkills(configDir, projectDir);
|
|
@@ -2099,10 +2216,12 @@ function isSkillEnabled(skillId) {
|
|
|
2099
2216
|
if (value === null) return true;
|
|
2100
2217
|
return value === "true";
|
|
2101
2218
|
}
|
|
2219
|
+
function setSkillEnabled(skillId, enabled) {
|
|
2220
|
+
setSetting(`${SKILL_SETTING_PREFIX}${skillId}`, String(enabled));
|
|
2221
|
+
}
|
|
2102
2222
|
async function getDefaultSkillIds() {
|
|
2103
|
-
const
|
|
2104
|
-
|
|
2105
|
-
return getDefaultIds(DEFAULTS_DIR_ALT2, SKILL_EXTENSION);
|
|
2223
|
+
const defaults = await loadDefaultSkills();
|
|
2224
|
+
return defaults.map((s) => s.metadata.id);
|
|
2106
2225
|
}
|
|
2107
2226
|
async function isDefaultSkill(skillId) {
|
|
2108
2227
|
const defaultIds = await getDefaultSkillIds();
|
|
@@ -2113,26 +2232,104 @@ function findSkillById(skillId, skills) {
|
|
|
2113
2232
|
}
|
|
2114
2233
|
async function skillExists(configDir, skillId, projectDir) {
|
|
2115
2234
|
if (await pathExists(join6(getSkillsDir(configDir), `${skillId}${SKILL_EXTENSION}`))) return true;
|
|
2235
|
+
if (await pathExists(join6(getSkillsDir(configDir), skillId, "SKILL.md"))) return true;
|
|
2116
2236
|
if (projectDir && await pathExists(join6(getProjectSkillsDir(projectDir), `${skillId}${SKILL_EXTENSION}`)))
|
|
2117
2237
|
return true;
|
|
2238
|
+
if (projectDir && await pathExists(join6(getProjectSkillsDir(projectDir), skillId, "SKILL.md"))) return true;
|
|
2118
2239
|
return false;
|
|
2119
2240
|
}
|
|
2120
|
-
|
|
2121
|
-
const
|
|
2122
|
-
if (
|
|
2123
|
-
|
|
2241
|
+
function portableFrontmatter(skill) {
|
|
2242
|
+
const metadata = {};
|
|
2243
|
+
if (skill.metadata.version) metadata["version"] = skill.metadata.version;
|
|
2244
|
+
if (skill.metadata.name !== skill.metadata.id) {
|
|
2245
|
+
metadata["openfox"] = { displayName: skill.metadata.name };
|
|
2124
2246
|
}
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2247
|
+
return {
|
|
2248
|
+
name: skill.metadata.id,
|
|
2249
|
+
description: skill.metadata.description,
|
|
2250
|
+
...Object.keys(metadata).length ? { metadata } : {}
|
|
2251
|
+
};
|
|
2252
|
+
}
|
|
2253
|
+
async function savePortableSkill(dir, skill) {
|
|
2254
|
+
const packageDir = join6(dir, skill.metadata.id);
|
|
2255
|
+
await mkdir4(packageDir, { recursive: true });
|
|
2256
|
+
await writeFile5(join6(packageDir, "SKILL.md"), matter3.stringify(skill.prompt, portableFrontmatter(skill)), "utf-8");
|
|
2257
|
+
}
|
|
2258
|
+
async function saveSkill(configDir, skill) {
|
|
2259
|
+
await savePortableSkill(getSkillsDir(configDir), skill);
|
|
2128
2260
|
}
|
|
2129
2261
|
async function saveSkillToProject(projectDir, skill) {
|
|
2130
|
-
await
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2262
|
+
await savePortableSkill(getProjectSkillsDir(projectDir), skill);
|
|
2263
|
+
}
|
|
2264
|
+
function asRecord(value) {
|
|
2265
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
2266
|
+
}
|
|
2267
|
+
function updatedPortableFrontmatter(existing, metadata) {
|
|
2268
|
+
const frontmatter = { ...existing.rawMetadata ?? {} };
|
|
2269
|
+
const portableMetadata = { ...asRecord(frontmatter["metadata"]) };
|
|
2270
|
+
const openfox = { ...asRecord(portableMetadata["openfox"]) };
|
|
2271
|
+
frontmatter["name"] = existing.metadata.id;
|
|
2272
|
+
frontmatter["description"] = metadata.description;
|
|
2273
|
+
if (metadata.version) portableMetadata["version"] = metadata.version;
|
|
2274
|
+
else delete portableMetadata["version"];
|
|
2275
|
+
if (metadata.name !== existing.metadata.id) openfox["displayName"] = metadata.name;
|
|
2276
|
+
else delete openfox["displayName"];
|
|
2277
|
+
if (Object.keys(openfox).length) portableMetadata["openfox"] = openfox;
|
|
2278
|
+
else delete portableMetadata["openfox"];
|
|
2279
|
+
if (Object.keys(portableMetadata).length) frontmatter["metadata"] = portableMetadata;
|
|
2280
|
+
else delete frontmatter["metadata"];
|
|
2281
|
+
return frontmatter;
|
|
2282
|
+
}
|
|
2283
|
+
function canModifySkill(existing) {
|
|
2284
|
+
if (existing.source === "global-openfox" || existing.source === "project-openfox") return true;
|
|
2285
|
+
return !existing.legacy && (existing.source === "global-shared" || existing.source === "selected" || existing.source === "project-shared");
|
|
2286
|
+
}
|
|
2287
|
+
async function updateOwnedSkill(existing, changes) {
|
|
2288
|
+
if (!existing.entrypoint || !canModifySkill(existing)) return null;
|
|
2289
|
+
const normalizedMetadata = {
|
|
2290
|
+
...existing.metadata,
|
|
2291
|
+
...changes.metadata ?? {},
|
|
2292
|
+
id: existing.metadata.id
|
|
2293
|
+
};
|
|
2294
|
+
if (!existing.legacy) {
|
|
2295
|
+
const frontmatter = updatedPortableFrontmatter(existing, normalizedMetadata);
|
|
2296
|
+
const updated2 = {
|
|
2297
|
+
...existing,
|
|
2298
|
+
...changes,
|
|
2299
|
+
metadata: normalizedMetadata,
|
|
2300
|
+
rawMetadata: frontmatter,
|
|
2301
|
+
prompt: changes.prompt ?? existing.prompt
|
|
2302
|
+
};
|
|
2303
|
+
await writeFile5(existing.entrypoint, matter3.stringify(updated2.prompt, frontmatter), "utf-8");
|
|
2304
|
+
return updated2;
|
|
2305
|
+
}
|
|
2306
|
+
const metadata = {
|
|
2307
|
+
...existing.rawMetadata ?? existing.metadata,
|
|
2308
|
+
...changes.metadata ?? {},
|
|
2309
|
+
id: existing.metadata.id
|
|
2310
|
+
};
|
|
2311
|
+
const updated = {
|
|
2312
|
+
...existing,
|
|
2313
|
+
...changes,
|
|
2314
|
+
metadata,
|
|
2315
|
+
rawMetadata: metadata,
|
|
2316
|
+
prompt: changes.prompt ?? existing.prompt
|
|
2317
|
+
};
|
|
2318
|
+
await writeFile5(existing.entrypoint, matter3.stringify(updated.prompt, metadata), "utf-8");
|
|
2319
|
+
return updated;
|
|
2320
|
+
}
|
|
2321
|
+
async function deleteOwnedSkill(existing) {
|
|
2322
|
+
if (!existing.entrypoint || !canModifySkill(existing)) {
|
|
2323
|
+
return { success: false, reason: "This skill is read-only" };
|
|
2324
|
+
}
|
|
2325
|
+
try {
|
|
2326
|
+
if (existing.legacy) await unlink3(existing.entrypoint);
|
|
2327
|
+
else await rm(dirname4(existing.entrypoint), { recursive: true });
|
|
2328
|
+
deleteSetting(`${SKILL_SETTING_PREFIX}${existing.metadata.id}`);
|
|
2329
|
+
return { success: true };
|
|
2330
|
+
} catch {
|
|
2331
|
+
return { success: false, reason: "Cannot delete this skill" };
|
|
2332
|
+
}
|
|
2136
2333
|
}
|
|
2137
2334
|
async function deleteSkill(configDir, skillId) {
|
|
2138
2335
|
const isDefault = await isDefaultSkill(skillId);
|
|
@@ -2910,7 +3107,7 @@ async function describeImageFromDataUrl(dataUrl, visionModel, options) {
|
|
|
2910
3107
|
import { createHash as createHash2 } from "crypto";
|
|
2911
3108
|
async function loadVisionModelFromGlobalConfig() {
|
|
2912
3109
|
try {
|
|
2913
|
-
const { loadGlobalConfig: loadGlobalConfig2, getVisionFallback } = await import("./config-
|
|
3110
|
+
const { loadGlobalConfig: loadGlobalConfig2, getVisionFallback } = await import("./config-GMQUPNBY.js");
|
|
2914
3111
|
const runtimeConfig = getRuntimeConfig();
|
|
2915
3112
|
const mode = runtimeConfig.mode ?? "production";
|
|
2916
3113
|
const globalConfig = await loadGlobalConfig2(mode);
|
|
@@ -3246,6 +3443,33 @@ function getWindowOptions(sessionId) {
|
|
|
3246
3443
|
const id = getCurrentContextWindowId(sessionId);
|
|
3247
3444
|
return id ? { contextWindowId: id } : void 0;
|
|
3248
3445
|
}
|
|
3446
|
+
async function loadGitIgnoreRules(workdir) {
|
|
3447
|
+
if (!isAbsolute3(workdir)) return "";
|
|
3448
|
+
let currentDir = workdir;
|
|
3449
|
+
while (true) {
|
|
3450
|
+
const gitignorePath = join7(currentDir, ".gitignore");
|
|
3451
|
+
try {
|
|
3452
|
+
await access4(gitignorePath);
|
|
3453
|
+
const content = await readFile8(gitignorePath, "utf-8");
|
|
3454
|
+
const trimmed = content.trim();
|
|
3455
|
+
if (!trimmed) return "";
|
|
3456
|
+
const lines = trimmed.split("\n");
|
|
3457
|
+
const capped = lines.slice(0, 100);
|
|
3458
|
+
if (capped.length < lines.length) capped.push("# ... truncated (too many patterns)");
|
|
3459
|
+
const final = capped.join("\n").slice(0, 4096);
|
|
3460
|
+
return `## Repository Exclusion Rules (.gitignore)
|
|
3461
|
+
|
|
3462
|
+
The following patterns from \`.gitignore\` should be excluded from file searches:
|
|
3463
|
+
|
|
3464
|
+
${final}`;
|
|
3465
|
+
} catch {
|
|
3466
|
+
}
|
|
3467
|
+
const parentDir = dirname5(currentDir);
|
|
3468
|
+
if (parentDir === currentDir) break;
|
|
3469
|
+
currentDir = parentDir;
|
|
3470
|
+
}
|
|
3471
|
+
return "";
|
|
3472
|
+
}
|
|
3249
3473
|
async function executeSubAgent(options) {
|
|
3250
3474
|
const {
|
|
3251
3475
|
subAgentType,
|
|
@@ -3317,7 +3541,9 @@ async function executeSubAgent(options) {
|
|
|
3317
3541
|
const config = getRuntimeConfig();
|
|
3318
3542
|
const configDir = getGlobalConfigDir(config.mode ?? "production");
|
|
3319
3543
|
const skills = await getEnabledSkillMetadata(configDir, config.workdir);
|
|
3320
|
-
const
|
|
3544
|
+
const hasRunCommand = agentDef.metadata.allowedTools?.includes("run_command") ?? false;
|
|
3545
|
+
const gitignoreSection = hasRunCommand ? await loadGitIgnoreRules(session.workdir) : "";
|
|
3546
|
+
const systemPrompt = buildBasePrompt(session.workdir, void 0, skills.length > 0 ? skills : void 0, llmClient.getModel()) + "\n\n" + agentDef.prompt + (gitignoreSection ? "\n\n" + gitignoreSection : "") + RETURN_VALUE_INSTRUCTION;
|
|
3321
3547
|
const subAgentScope = { type: "subagent", sessionId, subAgentId, subAgentType };
|
|
3322
3548
|
const loopResult = await runTopLevelAgentLoop(
|
|
3323
3549
|
{
|
|
@@ -3425,7 +3651,7 @@ var callSubAgentTool = {
|
|
|
3425
3651
|
};
|
|
3426
3652
|
}
|
|
3427
3653
|
try {
|
|
3428
|
-
const { getToolRegistryForAgent: getToolRegistryForAgent2 } = await import("./tools-
|
|
3654
|
+
const { getToolRegistryForAgent: getToolRegistryForAgent2 } = await import("./tools-WGAZKL56.js");
|
|
3429
3655
|
const toolRegistry = getToolRegistryForAgent2(agentDef);
|
|
3430
3656
|
const turnMetrics = new TurnMetrics();
|
|
3431
3657
|
const result = await executeSubAgent({
|
|
@@ -3463,6 +3689,13 @@ var callSubAgentTool = {
|
|
|
3463
3689
|
};
|
|
3464
3690
|
|
|
3465
3691
|
// src/server/tools/load-skill.ts
|
|
3692
|
+
function formatSkillPrompt(skill) {
|
|
3693
|
+
if (skill.legacy !== false || !skill.directory) return skill.prompt;
|
|
3694
|
+
return `Skill package directory: ${skill.directory}
|
|
3695
|
+
Resolve relative paths in these instructions from that directory.
|
|
3696
|
+
|
|
3697
|
+
${skill.prompt}`;
|
|
3698
|
+
}
|
|
3466
3699
|
var handler = async (args, _context, helpers) => {
|
|
3467
3700
|
const { skillId } = args;
|
|
3468
3701
|
if (!skillId) {
|
|
@@ -3479,7 +3712,7 @@ var handler = async (args, _context, helpers) => {
|
|
|
3479
3712
|
const available = allSkills.map((s) => s.metadata.id).join(", ");
|
|
3480
3713
|
return helpers.error(`Skill "${skillId}" not found. Available skills: ${available}`);
|
|
3481
3714
|
}
|
|
3482
|
-
return helpers.success(skill
|
|
3715
|
+
return helpers.success(formatSkillPrompt(skill));
|
|
3483
3716
|
};
|
|
3484
3717
|
var loadSkillTool = createTool(
|
|
3485
3718
|
"load_skill",
|
|
@@ -3676,13 +3909,13 @@ var webFetchTool = createTool(
|
|
|
3676
3909
|
|
|
3677
3910
|
// src/server/dev-server/manager.ts
|
|
3678
3911
|
import { spawn as spawn2 } from "child_process";
|
|
3679
|
-
import { readFile as
|
|
3680
|
-
import { resolve as resolve5, join as
|
|
3912
|
+
import { readFile as readFile9, writeFile as writeFile6, mkdir as mkdir5 } from "fs/promises";
|
|
3913
|
+
import { resolve as resolve5, join as join8 } from "path";
|
|
3681
3914
|
var MAX_LOG_LINES = 2e3;
|
|
3682
3915
|
var MAX_LOG_BYTES = 1e5;
|
|
3683
3916
|
var getDevServerConfigPath = (workdir) => {
|
|
3684
3917
|
const mode = getRuntimeConfig().mode ?? "production";
|
|
3685
|
-
return
|
|
3918
|
+
return join8(resolve5(workdir), ".openfox", `${mode === "development" ? "dev-dev" : "dev"}.json`);
|
|
3686
3919
|
};
|
|
3687
3920
|
var ERROR_PATTERNS = [
|
|
3688
3921
|
/EADDRINUSE/,
|
|
@@ -3743,7 +3976,7 @@ var DevServerManager = class {
|
|
|
3743
3976
|
async loadConfig(workdir) {
|
|
3744
3977
|
try {
|
|
3745
3978
|
const configPath = getDevServerConfigPath(workdir);
|
|
3746
|
-
const raw = await
|
|
3979
|
+
const raw = await readFile9(configPath, "utf-8");
|
|
3747
3980
|
const parsed = JSON.parse(raw);
|
|
3748
3981
|
if (!parsed.command || !parsed.url) return null;
|
|
3749
3982
|
return {
|
|
@@ -3758,7 +3991,7 @@ var DevServerManager = class {
|
|
|
3758
3991
|
}
|
|
3759
3992
|
async saveConfig(workdir, config) {
|
|
3760
3993
|
const resolved = this.resolveWorkdir(workdir);
|
|
3761
|
-
const dirPath =
|
|
3994
|
+
const dirPath = join8(resolved, ".openfox");
|
|
3762
3995
|
await mkdir5(dirPath, { recursive: true });
|
|
3763
3996
|
const configPath = getDevServerConfigPath(workdir);
|
|
3764
3997
|
await writeFile6(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
@@ -3793,7 +4026,8 @@ var DevServerManager = class {
|
|
|
3793
4026
|
cwd: resolved,
|
|
3794
4027
|
env: { ...process.env, FORCE_COLOR: "1" },
|
|
3795
4028
|
stdio: ["ignore", "pipe", "pipe"],
|
|
3796
|
-
detached: true
|
|
4029
|
+
detached: true,
|
|
4030
|
+
windowsHide: true
|
|
3797
4031
|
});
|
|
3798
4032
|
instance.process = proc;
|
|
3799
4033
|
const appendLog = (stream, content) => {
|
|
@@ -4241,7 +4475,7 @@ function resolveAgentDef2(sessionManager, sessionId) {
|
|
|
4241
4475
|
}
|
|
4242
4476
|
async function buildCachedPrompt(sessionManager, sessionId, agentDef) {
|
|
4243
4477
|
const { instructionContent, skills } = await loadSessionContext(sessionManager, sessionId);
|
|
4244
|
-
const { getToolRegistryForAgent: getToolRegistryForAgent2 } = await import("./tools-
|
|
4478
|
+
const { getToolRegistryForAgent: getToolRegistryForAgent2 } = await import("./tools-WGAZKL56.js");
|
|
4245
4479
|
const tools = getToolRegistryForAgent2(agentDef).definitions;
|
|
4246
4480
|
const toolFingerprint = getToolFingerprint(tools);
|
|
4247
4481
|
const allAgents = await loadAllAgentsDefault();
|
|
@@ -4254,7 +4488,7 @@ async function buildCachedPrompt(sessionManager, sessionId, agentDef) {
|
|
|
4254
4488
|
async function computeSessionHash(sessionManager, sessionId) {
|
|
4255
4489
|
const { instructionContent, skills } = await loadSessionContext(sessionManager, sessionId);
|
|
4256
4490
|
const agentDef = await resolveAgentDef2(sessionManager, sessionId);
|
|
4257
|
-
const { getToolRegistryForAgent: getToolRegistryForAgent2 } = await import("./tools-
|
|
4491
|
+
const { getToolRegistryForAgent: getToolRegistryForAgent2 } = await import("./tools-WGAZKL56.js");
|
|
4258
4492
|
const tools = getToolRegistryForAgent2(agentDef).definitions;
|
|
4259
4493
|
const toolFingerprint = getToolFingerprint(tools);
|
|
4260
4494
|
return computeDynamicContextHash(instructionContent, skills, toolFingerprint);
|
|
@@ -4273,6 +4507,7 @@ async function applyDynamicContext(sessionManager, sessionId) {
|
|
|
4273
4507
|
// src/server/tools/mcp-config.ts
|
|
4274
4508
|
var mcpManagerForTools = null;
|
|
4275
4509
|
var mcpConfigMode = "production";
|
|
4510
|
+
var mcpConfigPath;
|
|
4276
4511
|
var mcpNotifyChanged = null;
|
|
4277
4512
|
function setMcpManagerForTools(manager) {
|
|
4278
4513
|
mcpManagerForTools = manager;
|
|
@@ -4280,6 +4515,9 @@ function setMcpManagerForTools(manager) {
|
|
|
4280
4515
|
function setMcpConfigMode(mode) {
|
|
4281
4516
|
mcpConfigMode = mode;
|
|
4282
4517
|
}
|
|
4518
|
+
function setMcpConfigPath(path) {
|
|
4519
|
+
mcpConfigPath = path;
|
|
4520
|
+
}
|
|
4283
4521
|
function setNotifyMcpServersChanged(fn) {
|
|
4284
4522
|
mcpNotifyChanged = fn;
|
|
4285
4523
|
}
|
|
@@ -4355,13 +4593,13 @@ var mcpConfigTool = createTool(
|
|
|
4355
4593
|
return helpers.error("MCP manager not available");
|
|
4356
4594
|
}
|
|
4357
4595
|
async function persistAndRebuild(updater) {
|
|
4358
|
-
const globalConfig = await loadGlobalConfig(mcpConfigMode);
|
|
4596
|
+
const globalConfig = await loadGlobalConfig(mcpConfigMode, mcpConfigPath);
|
|
4359
4597
|
const mcpServers = { ...globalConfig.mcpServers ?? {} };
|
|
4360
4598
|
const updated = updater(mcpServers);
|
|
4361
|
-
await saveGlobalConfig(mcpConfigMode, { ...globalConfig, mcpServers: updated });
|
|
4599
|
+
await saveGlobalConfig(mcpConfigMode, { ...globalConfig, mcpServers: updated }, mcpConfigPath);
|
|
4362
4600
|
}
|
|
4363
4601
|
async function rebuildTools() {
|
|
4364
|
-
const { setMcpTools: setMcpTools2 } = await import("./tools-
|
|
4602
|
+
const { setMcpTools: setMcpTools2 } = await import("./tools-WGAZKL56.js");
|
|
4365
4603
|
const mcpTools = createMcpTools(mcpManagerForTools);
|
|
4366
4604
|
setMcpTools2(mcpTools);
|
|
4367
4605
|
}
|
|
@@ -4463,7 +4701,7 @@ var mcpConfigTool = createTool(
|
|
|
4463
4701
|
);
|
|
4464
4702
|
|
|
4465
4703
|
// src/server/tools/trace-code.ts
|
|
4466
|
-
import { stat as stat2, readFile as
|
|
4704
|
+
import { stat as stat2, readFile as readFile10 } from "fs/promises";
|
|
4467
4705
|
function graphNode(location, depth, relation, symbolName, symbolKind) {
|
|
4468
4706
|
const node = { location, depth, relation, symbolName };
|
|
4469
4707
|
if (symbolKind) node.symbolKind = symbolKind;
|
|
@@ -4495,7 +4733,7 @@ async function getCachedLines(path, approvedPaths) {
|
|
|
4495
4733
|
}
|
|
4496
4734
|
try {
|
|
4497
4735
|
const stats = await stat2(path);
|
|
4498
|
-
const content = await
|
|
4736
|
+
const content = await readFile10(path, "utf-8");
|
|
4499
4737
|
const lines = content.split("\n");
|
|
4500
4738
|
fileCache.set(path, { mtimeMs: stats.mtimeMs, lines });
|
|
4501
4739
|
if (fileCache.size > CACHE_MAX_SIZE) {
|
|
@@ -4997,14 +5235,18 @@ export {
|
|
|
4997
5235
|
loadUserSkills,
|
|
4998
5236
|
loadProjectSkills,
|
|
4999
5237
|
loadAllSkills,
|
|
5238
|
+
loadAllSkillsWithDiagnostics,
|
|
5000
5239
|
getEnabledSkillMetadata,
|
|
5001
5240
|
isSkillEnabled,
|
|
5241
|
+
setSkillEnabled,
|
|
5002
5242
|
getDefaultSkillIds,
|
|
5003
5243
|
isDefaultSkill,
|
|
5004
5244
|
findSkillById,
|
|
5005
5245
|
skillExists,
|
|
5006
5246
|
saveSkill,
|
|
5007
5247
|
saveSkillToProject,
|
|
5248
|
+
updateOwnedSkill,
|
|
5249
|
+
deleteOwnedSkill,
|
|
5008
5250
|
deleteSkill,
|
|
5009
5251
|
deleteProjectSkill,
|
|
5010
5252
|
runTopLevelAgentLoop,
|
|
@@ -5021,6 +5263,7 @@ export {
|
|
|
5021
5263
|
applyDynamicContext,
|
|
5022
5264
|
setMcpManagerForTools,
|
|
5023
5265
|
setMcpConfigMode,
|
|
5266
|
+
setMcpConfigPath,
|
|
5024
5267
|
setNotifyMcpServersChanged,
|
|
5025
5268
|
parseToolPermissions,
|
|
5026
5269
|
getToolPermissions,
|
|
@@ -5031,4 +5274,4 @@ export {
|
|
|
5031
5274
|
getToolRegistryForAgent,
|
|
5032
5275
|
createToolRegistry
|
|
5033
5276
|
};
|
|
5034
|
-
//# sourceMappingURL=chunk-
|
|
5277
|
+
//# sourceMappingURL=chunk-3JRYK5UG.js.map
|
|
@@ -125,8 +125,8 @@ var configSchema = z.object({
|
|
|
125
125
|
function getVisionFallback(config) {
|
|
126
126
|
return config.visionFallback ?? getDefaultVisionFallback();
|
|
127
127
|
}
|
|
128
|
-
async function loadGlobalConfig(mode) {
|
|
129
|
-
const configPath = getGlobalConfigPath(mode);
|
|
128
|
+
async function loadGlobalConfig(mode, configPathOverride) {
|
|
129
|
+
const configPath = configPathOverride ?? getGlobalConfigPath(mode);
|
|
130
130
|
try {
|
|
131
131
|
const content = await readFile(configPath, "utf-8");
|
|
132
132
|
const parsed = JSON.parse(content);
|
|
@@ -138,8 +138,8 @@ async function loadGlobalConfig(mode) {
|
|
|
138
138
|
function getDefaultVisionFallback() {
|
|
139
139
|
return { enabled: false, url: "http://localhost:11434", model: "qwen3.5:0.8b", timeout: 120 };
|
|
140
140
|
}
|
|
141
|
-
async function saveGlobalConfig(mode, config) {
|
|
142
|
-
const configPath = getGlobalConfigPath(mode);
|
|
141
|
+
async function saveGlobalConfig(mode, config, configPathOverride) {
|
|
142
|
+
const configPath = configPathOverride ?? getGlobalConfigPath(mode);
|
|
143
143
|
const fullConfig = {
|
|
144
144
|
providers: config.providers ?? [],
|
|
145
145
|
mcpServers: config.mcpServers,
|
|
@@ -291,4 +291,4 @@ export {
|
|
|
291
291
|
removeProvider,
|
|
292
292
|
activateProvider
|
|
293
293
|
};
|
|
294
|
-
//# sourceMappingURL=chunk-
|
|
294
|
+
//# sourceMappingURL=chunk-43UFGATL.js.map
|