openfox 1.6.91 → 1.6.93
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/{auto-compaction-I4YS2BN4.js → auto-compaction-WYN4P4R3.js} +6 -6
- package/dist/{chat-handler-O4FNSVPI.js → chat-handler-ROOMX2UY.js} +9 -9
- package/dist/{chunk-CL2ZPJAG.js → chunk-32WAUDDK.js} +225 -138
- package/dist/{chunk-SSGVISQU.js → chunk-LABBIL3K.js} +9 -8
- package/dist/{chunk-STUSQVXQ.js → chunk-RMQ4WCEK.js} +2 -2
- package/dist/{chunk-B5AP3RSV.js → chunk-RW25DL5R.js} +3 -3
- package/dist/{chunk-A3YOBYWJ.js → chunk-TWGL3Y6S.js} +5 -5
- package/dist/{chunk-UQSL65WB.js → chunk-UAV33LRW.js} +399 -471
- package/dist/{chunk-DF5BZBP6.js → chunk-XGJ7HDQ7.js} +2 -2
- package/dist/{chunk-H5T34J3H.js → chunk-YG2QBUYJ.js} +12 -12
- package/dist/{chunk-6P5WQP6Y.js → chunk-YTPPQK55.js} +2 -2
- package/dist/{chunk-MOQLMPTA.js → chunk-Z774ZQUP.js} +5 -5
- package/dist/{chunk-HKCUSLQ5.js → chunk-ZK3EZTHT.js} +3 -3
- package/dist/{chunk-II4UCFTE.js → chunk-ZV2PE3KT.js} +3 -3
- package/dist/cli/dev.js +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/{config-GEDIDCBM.js → config-TSGOFNJW.js} +5 -5
- package/dist/{events-AQKDXJFK.js → events-K6AYMXFT.js} +3 -3
- package/dist/{orchestrator-LLOIG2CR.js → orchestrator-5I4LBRSY.js} +7 -7
- package/dist/package.json +1 -1
- package/dist/{processor-XL5NULQN.js → processor-47OC5EUI.js} +5 -5
- package/dist/{protocol--8PKNwb_.d.ts → protocol-XRiJzlOK.d.ts} +1 -1
- package/dist/{provider-EV3KBC7Y.js → provider-JIFQ47HT.js} +7 -7
- package/dist/{runtime-config-CBJJJGBD.js → runtime-config-CYHDAC7W.js} +2 -2
- package/dist/{serve-UWKYNKAO.js → serve-JQTSGHFU.js} +11 -11
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +9 -9
- package/dist/shared/index.d.ts +2 -2
- package/dist/{tools-ZBAAAOUH.js → tools-U6I43EN4.js} +6 -6
- package/dist/{vision-fallback-4TAGWGVS.js → vision-fallback-FBOTVWEX.js} +2 -2
- package/dist/web/assets/{index-CGEQK8Pf.css → index-CM0cLwa6.css} +1 -1
- package/dist/web/assets/index-CjiS1Y5o.js +176 -0
- package/dist/web/index.html +2 -2
- package/dist/web/sw.js +1 -1
- package/package.json +1 -1
- package/dist/web/assets/index-Cb7XVDFv.js +0 -158
- /package/dist/web/{workbox-8c29f6e4.js → workbox-7fc22fbe.js} +0 -0
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
createVerifierNudgeConfig,
|
|
3
3
|
runBuilderTurn,
|
|
4
4
|
runChatTurn
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-ZK3EZTHT.js";
|
|
6
6
|
import {
|
|
7
7
|
TurnMetrics,
|
|
8
8
|
agentExists,
|
|
@@ -10,35 +10,43 @@ import {
|
|
|
10
10
|
createMessageStartEvent,
|
|
11
11
|
createToolRegistry,
|
|
12
12
|
deleteAgent,
|
|
13
|
+
deleteItemFromDir,
|
|
14
|
+
deleteProjectAgent,
|
|
15
|
+
deleteProjectSkill,
|
|
13
16
|
deleteSkill,
|
|
14
17
|
devServerManager,
|
|
15
18
|
executeSubAgent,
|
|
16
19
|
findAgentById,
|
|
17
20
|
findSkillById,
|
|
18
|
-
getDefaultAgentContent,
|
|
19
21
|
getDefaultAgentIds,
|
|
20
22
|
getDefaultIds,
|
|
21
|
-
getDefaultSkillContent,
|
|
22
23
|
getDefaultSkillIds,
|
|
23
24
|
getToolRegistryForAgent,
|
|
24
25
|
getTopLevelAgents,
|
|
26
|
+
isDefaultAgent,
|
|
27
|
+
isDefaultSkill,
|
|
25
28
|
isSkillEnabled,
|
|
29
|
+
jsonSerializer,
|
|
26
30
|
loadAllAgents,
|
|
27
31
|
loadAllAgentsDefault,
|
|
28
32
|
loadAllSkills,
|
|
29
33
|
loadDefaultAgents,
|
|
30
34
|
loadDefaultSkills,
|
|
31
35
|
loadItemsFromDir,
|
|
36
|
+
loadProjectAgents,
|
|
37
|
+
loadProjectSkills,
|
|
32
38
|
loadUserAgents,
|
|
33
39
|
loadUserSkills,
|
|
34
40
|
pathExists,
|
|
35
41
|
performManualContextCompaction,
|
|
36
42
|
saveAgent,
|
|
43
|
+
saveAgentToProject,
|
|
44
|
+
saveItemToDir,
|
|
37
45
|
saveSkill,
|
|
38
|
-
|
|
46
|
+
saveSkillToProject,
|
|
39
47
|
skillExists,
|
|
40
48
|
spawnShellProcess
|
|
41
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-32WAUDDK.js";
|
|
42
50
|
import {
|
|
43
51
|
getProject
|
|
44
52
|
} from "./chunk-ZHBL5G5X.js";
|
|
@@ -51,18 +59,18 @@ import {
|
|
|
51
59
|
import {
|
|
52
60
|
createProviderManager,
|
|
53
61
|
parseDefaultModelSelection
|
|
54
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-ZV2PE3KT.js";
|
|
55
63
|
import {
|
|
56
64
|
SessionNotFoundError,
|
|
57
65
|
createLLMClient,
|
|
58
66
|
detectModel,
|
|
59
67
|
getLlmStatus
|
|
60
|
-
} from "./chunk-
|
|
68
|
+
} from "./chunk-TWGL3Y6S.js";
|
|
61
69
|
import {
|
|
62
70
|
detectBackend,
|
|
63
71
|
getBackendDisplayName,
|
|
64
72
|
getModelProfile
|
|
65
|
-
} from "./chunk-
|
|
73
|
+
} from "./chunk-RMQ4WCEK.js";
|
|
66
74
|
import {
|
|
67
75
|
createSession,
|
|
68
76
|
deleteSession,
|
|
@@ -88,7 +96,7 @@ import {
|
|
|
88
96
|
updateSessionProvider,
|
|
89
97
|
updateSessionRunning,
|
|
90
98
|
updateSessionSummary
|
|
91
|
-
} from "./chunk-
|
|
99
|
+
} from "./chunk-YTPPQK55.js";
|
|
92
100
|
import {
|
|
93
101
|
initDatabase
|
|
94
102
|
} from "./chunk-5GVCNVKV.js";
|
|
@@ -127,7 +135,7 @@ import {
|
|
|
127
135
|
import {
|
|
128
136
|
getRuntimeConfig,
|
|
129
137
|
setRuntimeConfig
|
|
130
|
-
} from "./chunk-
|
|
138
|
+
} from "./chunk-RW25DL5R.js";
|
|
131
139
|
import {
|
|
132
140
|
logger,
|
|
133
141
|
setLogLevel
|
|
@@ -138,7 +146,7 @@ import express from "express";
|
|
|
138
146
|
import cors from "cors";
|
|
139
147
|
import { createServer as createHttpServer } from "http";
|
|
140
148
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
141
|
-
import { dirname as dirname5, resolve, join as
|
|
149
|
+
import { dirname as dirname5, resolve, join as join6 } from "path";
|
|
142
150
|
import { readFile as readFile3 } from "fs/promises";
|
|
143
151
|
import { createServer as createViteServer } from "vite";
|
|
144
152
|
|
|
@@ -1532,6 +1540,9 @@ var WORKFLOW_EXTENSION = ".workflow.json";
|
|
|
1532
1540
|
function getWorkflowsDir(configDir) {
|
|
1533
1541
|
return join(configDir, "workflows");
|
|
1534
1542
|
}
|
|
1543
|
+
function getProjectWorkflowsDir(projectDir) {
|
|
1544
|
+
return join(projectDir, ".openfox", "workflows");
|
|
1545
|
+
}
|
|
1535
1546
|
async function pathExists2(path) {
|
|
1536
1547
|
try {
|
|
1537
1548
|
await access(path, constants.R_OK);
|
|
@@ -1576,7 +1587,10 @@ async function loadDefaultWorkflows() {
|
|
|
1576
1587
|
async function loadUserWorkflows(configDir) {
|
|
1577
1588
|
return loadWorkflowsFromDir(getWorkflowsDir(configDir));
|
|
1578
1589
|
}
|
|
1579
|
-
async function
|
|
1590
|
+
async function loadProjectWorkflows(projectDir) {
|
|
1591
|
+
return loadWorkflowsFromDir(getProjectWorkflowsDir(projectDir));
|
|
1592
|
+
}
|
|
1593
|
+
async function loadAllWorkflows(configDir, projectDir) {
|
|
1580
1594
|
const [defaultWorkflows, userWorkflows] = await Promise.all([loadDefaultWorkflows(), loadUserWorkflows(configDir)]);
|
|
1581
1595
|
const workflowMap = /* @__PURE__ */ new Map();
|
|
1582
1596
|
for (const workflow of defaultWorkflows) {
|
|
@@ -1585,8 +1599,20 @@ async function loadAllWorkflows(configDir) {
|
|
|
1585
1599
|
for (const workflow of userWorkflows) {
|
|
1586
1600
|
workflowMap.set(workflow.metadata.id, workflow);
|
|
1587
1601
|
}
|
|
1602
|
+
if (projectDir) {
|
|
1603
|
+
const projectWorkflows = await loadProjectWorkflows(projectDir);
|
|
1604
|
+
for (const workflow of projectWorkflows) {
|
|
1605
|
+
workflowMap.set(workflow.metadata.id, workflow);
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1588
1608
|
return Array.from(workflowMap.values());
|
|
1589
1609
|
}
|
|
1610
|
+
async function saveWorkflowToProject(projectDir, workflow) {
|
|
1611
|
+
await saveItemToDir(getProjectWorkflowsDir(projectDir), workflow, WORKFLOW_EXTENSION, jsonSerializer);
|
|
1612
|
+
}
|
|
1613
|
+
async function deleteProjectWorkflow(projectDir, workflowId) {
|
|
1614
|
+
return deleteItemFromDir(getProjectWorkflowsDir(projectDir), workflowId, WORKFLOW_EXTENSION);
|
|
1615
|
+
}
|
|
1590
1616
|
async function getDefaultWorkflowIds() {
|
|
1591
1617
|
for (const dir of [DEFAULTS_DIR, DEFAULTS_DIR_ALT]) {
|
|
1592
1618
|
try {
|
|
@@ -1597,10 +1623,6 @@ async function getDefaultWorkflowIds() {
|
|
|
1597
1623
|
}
|
|
1598
1624
|
return [];
|
|
1599
1625
|
}
|
|
1600
|
-
async function getDefaultWorkflowContent(workflowId) {
|
|
1601
|
-
const defaults = await loadDefaultWorkflows();
|
|
1602
|
-
return defaults.find((w) => w.metadata.id === workflowId) ?? null;
|
|
1603
|
-
}
|
|
1604
1626
|
async function isDefaultWorkflow(workflowId) {
|
|
1605
1627
|
const defaultIds = await getDefaultWorkflowIds();
|
|
1606
1628
|
return defaultIds.includes(workflowId);
|
|
@@ -1608,9 +1630,11 @@ async function isDefaultWorkflow(workflowId) {
|
|
|
1608
1630
|
function findWorkflowById(workflowId, workflows) {
|
|
1609
1631
|
return workflows.find((p) => p.metadata.id === workflowId);
|
|
1610
1632
|
}
|
|
1611
|
-
async function workflowExists(configDir, workflowId) {
|
|
1612
|
-
|
|
1613
|
-
|
|
1633
|
+
async function workflowExists(configDir, workflowId, projectDir) {
|
|
1634
|
+
if (await pathExists2(join(getWorkflowsDir(configDir), `${workflowId}${WORKFLOW_EXTENSION}`))) return true;
|
|
1635
|
+
if (projectDir && await pathExists2(join(getProjectWorkflowsDir(projectDir), `${workflowId}${WORKFLOW_EXTENSION}`)))
|
|
1636
|
+
return true;
|
|
1637
|
+
return false;
|
|
1614
1638
|
}
|
|
1615
1639
|
async function saveWorkflow(configDir, workflow) {
|
|
1616
1640
|
const workflowsDir = getWorkflowsDir(configDir);
|
|
@@ -2481,7 +2505,7 @@ function processQueueAndRestartTurn(sessionManager, sessionId, drainFn, queueMod
|
|
|
2481
2505
|
}
|
|
2482
2506
|
var activeAgents = /* @__PURE__ */ new Map();
|
|
2483
2507
|
var MAX_SEND_QUEUE_SIZE = 1e3;
|
|
2484
|
-
function createWebSocketServer(httpServer,
|
|
2508
|
+
function createWebSocketServer(httpServer, config4, getLLMClient, getActiveProvider, sessionManager, providerManager) {
|
|
2485
2509
|
const wss = new WebSocketServer({ server: httpServer });
|
|
2486
2510
|
const clients = /* @__PURE__ */ new Map();
|
|
2487
2511
|
moduleClients = clients;
|
|
@@ -2508,9 +2532,9 @@ function createWebSocketServer(httpServer, config, getLLMClient, getActiveProvid
|
|
|
2508
2532
|
}
|
|
2509
2533
|
const baseUrl = provider.url.includes("/v1") ? provider.url : `${provider.url}/v1`;
|
|
2510
2534
|
const sessionConfig = {
|
|
2511
|
-
...
|
|
2535
|
+
...config4,
|
|
2512
2536
|
llm: {
|
|
2513
|
-
...
|
|
2537
|
+
...config4.llm,
|
|
2514
2538
|
baseUrl,
|
|
2515
2539
|
model: session.providerModel,
|
|
2516
2540
|
...provider.apiKey && { apiKey: provider.apiKey }
|
|
@@ -3114,10 +3138,10 @@ var LspServer = class {
|
|
|
3114
3138
|
// Pending diagnostic waiters
|
|
3115
3139
|
pendingDiagnostics = /* @__PURE__ */ new Map();
|
|
3116
3140
|
commandPath;
|
|
3117
|
-
constructor(
|
|
3118
|
-
this.config =
|
|
3141
|
+
constructor(config4, workdir, commandPath) {
|
|
3142
|
+
this.config = config4;
|
|
3119
3143
|
this.workdir = workdir;
|
|
3120
|
-
this.commandPath = commandPath ??
|
|
3144
|
+
this.commandPath = commandPath ?? config4.serverCommand;
|
|
3121
3145
|
}
|
|
3122
3146
|
// ============================================================================
|
|
3123
3147
|
// Lifecycle
|
|
@@ -3940,8 +3964,8 @@ var LspManager = class {
|
|
|
3940
3964
|
// ============================================================================
|
|
3941
3965
|
// Server Management
|
|
3942
3966
|
// ============================================================================
|
|
3943
|
-
async getOrCreateServer(
|
|
3944
|
-
const langId =
|
|
3967
|
+
async getOrCreateServer(config4) {
|
|
3968
|
+
const langId = config4.id;
|
|
3945
3969
|
const existing = this.servers.get(langId);
|
|
3946
3970
|
if (existing?.isRunning()) {
|
|
3947
3971
|
return existing;
|
|
@@ -3953,7 +3977,7 @@ var LspManager = class {
|
|
|
3953
3977
|
if (pending) {
|
|
3954
3978
|
return pending;
|
|
3955
3979
|
}
|
|
3956
|
-
const promise = this.startServer(
|
|
3980
|
+
const promise = this.startServer(config4);
|
|
3957
3981
|
this.serverPromises.set(langId, promise);
|
|
3958
3982
|
try {
|
|
3959
3983
|
const server = await promise;
|
|
@@ -3962,19 +3986,19 @@ var LspManager = class {
|
|
|
3962
3986
|
this.serverPromises.delete(langId);
|
|
3963
3987
|
}
|
|
3964
3988
|
}
|
|
3965
|
-
async startServer(
|
|
3966
|
-
const langId =
|
|
3967
|
-
const commandPath = await which(
|
|
3989
|
+
async startServer(config4) {
|
|
3990
|
+
const langId = config4.id;
|
|
3991
|
+
const commandPath = await which(config4.serverCommand, this.workdir);
|
|
3968
3992
|
if (!commandPath) {
|
|
3969
3993
|
logger.warn("LSP server not installed, skipping", {
|
|
3970
3994
|
language: langId,
|
|
3971
|
-
command:
|
|
3995
|
+
command: config4.serverCommand,
|
|
3972
3996
|
sessionId: this.sessionId
|
|
3973
3997
|
});
|
|
3974
3998
|
this.unavailableServers.add(langId);
|
|
3975
3999
|
return null;
|
|
3976
4000
|
}
|
|
3977
|
-
const server = new LspServer(
|
|
4001
|
+
const server = new LspServer(config4, this.workdir, commandPath);
|
|
3978
4002
|
try {
|
|
3979
4003
|
await server.start();
|
|
3980
4004
|
this.servers.set(langId, server);
|
|
@@ -3994,11 +4018,11 @@ var LspManager = class {
|
|
|
3994
4018
|
}
|
|
3995
4019
|
}
|
|
3996
4020
|
async getServerForFile(path) {
|
|
3997
|
-
const
|
|
3998
|
-
if (!
|
|
4021
|
+
const config4 = detectLanguage(path);
|
|
4022
|
+
if (!config4) {
|
|
3999
4023
|
return null;
|
|
4000
4024
|
}
|
|
4001
|
-
return this.getOrCreateServer(
|
|
4025
|
+
return this.getOrCreateServer(config4);
|
|
4002
4026
|
}
|
|
4003
4027
|
// ============================================================================
|
|
4004
4028
|
// Public Interface
|
|
@@ -4029,11 +4053,11 @@ var LspManager = class {
|
|
|
4029
4053
|
* Get current diagnostics for a file without triggering a change.
|
|
4030
4054
|
*/
|
|
4031
4055
|
getDiagnostics(path) {
|
|
4032
|
-
const
|
|
4033
|
-
if (!
|
|
4056
|
+
const config4 = detectLanguage(path);
|
|
4057
|
+
if (!config4) {
|
|
4034
4058
|
return [];
|
|
4035
4059
|
}
|
|
4036
|
-
const server = this.servers.get(
|
|
4060
|
+
const server = this.servers.get(config4.id);
|
|
4037
4061
|
if (!server?.isRunning()) {
|
|
4038
4062
|
return [];
|
|
4039
4063
|
}
|
|
@@ -4044,11 +4068,11 @@ var LspManager = class {
|
|
|
4044
4068
|
* Returns true if we have or can start a server for this file type.
|
|
4045
4069
|
*/
|
|
4046
4070
|
isAvailableFor(path) {
|
|
4047
|
-
const
|
|
4048
|
-
if (!
|
|
4071
|
+
const config4 = detectLanguage(path);
|
|
4072
|
+
if (!config4) {
|
|
4049
4073
|
return false;
|
|
4050
4074
|
}
|
|
4051
|
-
if (this.unavailableServers.has(
|
|
4075
|
+
if (this.unavailableServers.has(config4.id)) {
|
|
4052
4076
|
return false;
|
|
4053
4077
|
}
|
|
4054
4078
|
return true;
|
|
@@ -4836,130 +4860,197 @@ ${summary}`,
|
|
|
4836
4860
|
}
|
|
4837
4861
|
};
|
|
4838
4862
|
|
|
4839
|
-
// src/server/routes/skills.ts
|
|
4840
|
-
import { Router } from "express";
|
|
4841
|
-
|
|
4842
4863
|
// src/server/routes/crud-helpers.ts
|
|
4864
|
+
import { Router } from "express";
|
|
4865
|
+
import { join as join4 } from "path";
|
|
4843
4866
|
function computeOverrideIds(defaults, userItems) {
|
|
4844
4867
|
return userItems.filter((u) => defaults.some((d) => d.metadata.id === u.metadata.id)).map((u) => u.metadata.id);
|
|
4845
4868
|
}
|
|
4846
|
-
|
|
4847
|
-
|
|
4848
|
-
|
|
4869
|
+
var ID_REGEX = /^[a-z0-9-]+$/;
|
|
4870
|
+
function validateNameIdPrompt(body) {
|
|
4871
|
+
const meta = body["metadata"];
|
|
4872
|
+
if (!meta?.["name"] || !body["prompt"]) return "Missing required fields: metadata.name, prompt";
|
|
4873
|
+
if (meta["id"] && !ID_REGEX.test(String(meta["id"]))) return "ID must be lowercase alphanumeric with hyphens only";
|
|
4874
|
+
return null;
|
|
4875
|
+
}
|
|
4876
|
+
function getProjectItemPath(projectDir, dirName, id, ext) {
|
|
4877
|
+
return join4(projectDir, ".openfox", dirName, `${id}${ext}`);
|
|
4878
|
+
}
|
|
4879
|
+
async function isProjectItem(projectDir, dirName, id, ext) {
|
|
4880
|
+
if (!projectDir) return false;
|
|
4881
|
+
return pathExists(getProjectItemPath(projectDir, dirName, id, ext));
|
|
4882
|
+
}
|
|
4883
|
+
function createCrudRoutes(config4, configDir, projectDir) {
|
|
4849
4884
|
const router = Router();
|
|
4850
4885
|
router.get("/", async (_req, res) => {
|
|
4851
|
-
const [defaults, userItems] = await Promise.all([
|
|
4852
|
-
|
|
4886
|
+
const [defaults, userItems, projectItems] = await Promise.all([
|
|
4887
|
+
config4.loadDefaults(),
|
|
4888
|
+
config4.loadUser(configDir),
|
|
4889
|
+
projectDir ? config4.loadProject(projectDir) : []
|
|
4890
|
+
]);
|
|
4891
|
+
const userOverrideIds = computeOverrideIds(defaults, userItems);
|
|
4892
|
+
const projectOverrideIds = computeOverrideIds(defaults, projectItems);
|
|
4893
|
+
const extra = config4.extraGetData ? await config4.extraGetData() : {};
|
|
4853
4894
|
res.json({
|
|
4854
|
-
defaults: defaults.map(
|
|
4855
|
-
|
|
4856
|
-
|
|
4857
|
-
|
|
4858
|
-
|
|
4859
|
-
...s.metadata,
|
|
4860
|
-
enabled: isSkillEnabled(s.metadata.id)
|
|
4861
|
-
})),
|
|
4862
|
-
overrideIds
|
|
4895
|
+
defaults: defaults.map(config4.mapToResponse),
|
|
4896
|
+
userItems: userItems.map(config4.mapToResponse),
|
|
4897
|
+
projectItems: projectItems.map(config4.mapToResponse),
|
|
4898
|
+
overrideIds: [...userOverrideIds, ...projectOverrideIds],
|
|
4899
|
+
...extra
|
|
4863
4900
|
});
|
|
4864
4901
|
});
|
|
4865
4902
|
router.get("/defaults/:id", async (req, res) => {
|
|
4866
4903
|
const { id } = req.params;
|
|
4867
|
-
const
|
|
4868
|
-
|
|
4869
|
-
|
|
4904
|
+
const allDefaults = await config4.loadDefaults();
|
|
4905
|
+
const item = allDefaults.find((d) => d.metadata.id === id);
|
|
4906
|
+
if (!item) {
|
|
4907
|
+
return res.status(404).json({ error: "Default not found" });
|
|
4870
4908
|
}
|
|
4871
|
-
res.json(
|
|
4909
|
+
res.json(item);
|
|
4872
4910
|
});
|
|
4873
4911
|
router.get("/default-ids", async (_req, res) => {
|
|
4874
|
-
const ids = await
|
|
4912
|
+
const ids = config4.getDefaultIds ? await config4.getDefaultIds() : [];
|
|
4875
4913
|
res.json({ ids });
|
|
4876
4914
|
});
|
|
4877
|
-
router.post("/:id/toggle", (req, res) => {
|
|
4878
|
-
const { id } = req.params;
|
|
4879
|
-
const currentlyEnabled = isSkillEnabled(id);
|
|
4880
|
-
setSkillEnabled(id, !currentlyEnabled);
|
|
4881
|
-
res.json({ id, enabled: !currentlyEnabled });
|
|
4882
|
-
});
|
|
4883
4915
|
router.get("/:id", async (req, res) => {
|
|
4884
4916
|
const { id } = req.params;
|
|
4885
|
-
const
|
|
4886
|
-
const
|
|
4887
|
-
if (!
|
|
4888
|
-
return res.status(404).json({ error: "
|
|
4917
|
+
const items = await config4.loadAll(configDir, projectDir);
|
|
4918
|
+
const item = config4.findById(id, items);
|
|
4919
|
+
if (!item) {
|
|
4920
|
+
return res.status(404).json({ error: "Not found" });
|
|
4889
4921
|
}
|
|
4890
|
-
res.json(
|
|
4922
|
+
res.json(item);
|
|
4891
4923
|
});
|
|
4892
4924
|
router.post("/", async (req, res) => {
|
|
4893
4925
|
const body = req.body;
|
|
4894
|
-
|
|
4895
|
-
|
|
4926
|
+
const meta = body["metadata"];
|
|
4927
|
+
const customError = config4.validateCreate?.(body);
|
|
4928
|
+
if (!meta?.["id"] || customError) {
|
|
4929
|
+
return res.status(400).json({ error: customError ?? "Missing required fields" });
|
|
4896
4930
|
}
|
|
4897
|
-
|
|
4898
|
-
|
|
4931
|
+
const id = String(meta["id"]);
|
|
4932
|
+
const destination = body["destination"] ?? "user";
|
|
4933
|
+
if (destination === "project" && !projectDir) {
|
|
4934
|
+
return res.status(400).json({ error: "No project directory configured" });
|
|
4899
4935
|
}
|
|
4900
|
-
const exists = await
|
|
4936
|
+
const exists = await config4.exists(configDir, id, projectDir);
|
|
4901
4937
|
if (exists) {
|
|
4902
|
-
return res.status(409).json({ error: "
|
|
4938
|
+
return res.status(409).json({ error: "An item with this ID already exists" });
|
|
4939
|
+
}
|
|
4940
|
+
if (destination === "project") {
|
|
4941
|
+
await config4.saveToProject(projectDir, body);
|
|
4942
|
+
} else {
|
|
4943
|
+
await config4.save(configDir, body);
|
|
4903
4944
|
}
|
|
4904
|
-
await saveSkill(configDir, body);
|
|
4905
4945
|
res.status(201).json(body);
|
|
4906
4946
|
});
|
|
4907
4947
|
router.put("/:id", async (req, res) => {
|
|
4908
4948
|
const { id } = req.params;
|
|
4909
|
-
const
|
|
4910
|
-
const existing =
|
|
4949
|
+
const items = await config4.loadAll(configDir, projectDir);
|
|
4950
|
+
const existing = config4.findById(id, items);
|
|
4911
4951
|
if (!existing) {
|
|
4912
|
-
return res.status(404).json({ error: "
|
|
4952
|
+
return res.status(404).json({ error: "Not found" });
|
|
4913
4953
|
}
|
|
4914
4954
|
const body = req.body;
|
|
4955
|
+
const meta = body["metadata"];
|
|
4915
4956
|
const updated = {
|
|
4916
|
-
|
|
4917
|
-
|
|
4957
|
+
...existing,
|
|
4958
|
+
...body,
|
|
4959
|
+
metadata: { ...existing.metadata, ...meta, id }
|
|
4918
4960
|
};
|
|
4919
|
-
await
|
|
4961
|
+
const isProject = await isProjectItem(projectDir, config4.dirName, id, config4.ext);
|
|
4962
|
+
if (isProject) {
|
|
4963
|
+
await config4.saveToProject(projectDir, updated);
|
|
4964
|
+
} else {
|
|
4965
|
+
await config4.save(configDir, updated);
|
|
4966
|
+
}
|
|
4920
4967
|
res.json(updated);
|
|
4921
4968
|
});
|
|
4922
4969
|
router.delete("/:id", async (req, res) => {
|
|
4923
4970
|
const { id } = req.params;
|
|
4924
|
-
const
|
|
4971
|
+
const isProject = await isProjectItem(projectDir, config4.dirName, id, config4.ext);
|
|
4972
|
+
if (isProject) {
|
|
4973
|
+
const result2 = await config4.deleteProject(projectDir, id);
|
|
4974
|
+
if (!result2.success) {
|
|
4975
|
+
return res.status(500).json({ error: "Failed to delete project item" });
|
|
4976
|
+
}
|
|
4977
|
+
return res.json({ success: true });
|
|
4978
|
+
}
|
|
4979
|
+
const isDefault = await config4.isDefault(id);
|
|
4980
|
+
if (isDefault) {
|
|
4981
|
+
return res.status(403).json({ error: "Cannot delete built-in defaults" });
|
|
4982
|
+
}
|
|
4983
|
+
const result = await config4.delete(configDir, id);
|
|
4925
4984
|
if (!result.success) {
|
|
4926
|
-
return res.status(403).json({ error: result.reason ?? "Cannot delete this
|
|
4985
|
+
return res.status(403).json({ error: result.reason ?? "Cannot delete this item" });
|
|
4927
4986
|
}
|
|
4928
4987
|
res.json({ success: true });
|
|
4929
4988
|
});
|
|
4930
4989
|
router.post("/:id/duplicate", async (req, res) => {
|
|
4931
4990
|
const { id } = req.params;
|
|
4932
|
-
const
|
|
4933
|
-
const
|
|
4934
|
-
const source = defaults.find((s) => s.metadata.id === id) ?? userItems.find((s) => s.metadata.id === id);
|
|
4991
|
+
const items = await config4.loadAll(configDir, projectDir);
|
|
4992
|
+
const source = config4.findById(id, items);
|
|
4935
4993
|
if (!source) {
|
|
4936
|
-
return res.status(404).json({ error: "
|
|
4994
|
+
return res.status(404).json({ error: "Not found" });
|
|
4937
4995
|
}
|
|
4938
4996
|
const newId = `${id}-copy-${Date.now()}`;
|
|
4939
4997
|
const duplicated = {
|
|
4940
|
-
|
|
4941
|
-
|
|
4998
|
+
...source,
|
|
4999
|
+
metadata: { ...source.metadata, id: newId, name: `${source.metadata.name} (copy)` }
|
|
4942
5000
|
};
|
|
4943
|
-
|
|
5001
|
+
const destination = req.body.destination ?? "user";
|
|
5002
|
+
if (destination === "project") {
|
|
5003
|
+
if (!projectDir) return res.status(400).json({ error: "No project directory configured" });
|
|
5004
|
+
await config4.saveToProject(projectDir, duplicated);
|
|
5005
|
+
} else {
|
|
5006
|
+
await config4.save(configDir, duplicated);
|
|
5007
|
+
}
|
|
4944
5008
|
res.status(201).json(duplicated);
|
|
4945
5009
|
});
|
|
5010
|
+
config4.extraRoutes?.(router);
|
|
4946
5011
|
return router;
|
|
4947
5012
|
}
|
|
4948
5013
|
|
|
4949
|
-
// src/server/routes/
|
|
4950
|
-
|
|
5014
|
+
// src/server/routes/skills.ts
|
|
5015
|
+
var config = {
|
|
5016
|
+
dirName: "skills",
|
|
5017
|
+
ext: ".skill.md",
|
|
5018
|
+
loadDefaults: loadDefaultSkills,
|
|
5019
|
+
loadUser: loadUserSkills,
|
|
5020
|
+
loadProject: loadProjectSkills,
|
|
5021
|
+
loadAll: loadAllSkills,
|
|
5022
|
+
findById: findSkillById,
|
|
5023
|
+
save: saveSkill,
|
|
5024
|
+
saveToProject: saveSkillToProject,
|
|
5025
|
+
delete: deleteSkill,
|
|
5026
|
+
deleteProject: deleteProjectSkill,
|
|
5027
|
+
exists: skillExists,
|
|
5028
|
+
isDefault: isDefaultSkill,
|
|
5029
|
+
getDefaultIds: getDefaultSkillIds,
|
|
5030
|
+
validateCreate: validateNameIdPrompt,
|
|
5031
|
+
mapToResponse: (s) => ({
|
|
5032
|
+
...s.metadata,
|
|
5033
|
+
enabled: isSkillEnabled(s.metadata.id)
|
|
5034
|
+
})
|
|
5035
|
+
};
|
|
5036
|
+
function createSkillRoutes(configDir, projectDir) {
|
|
5037
|
+
return createCrudRoutes(config, configDir, projectDir);
|
|
5038
|
+
}
|
|
4951
5039
|
|
|
4952
5040
|
// src/server/commands/registry.ts
|
|
4953
5041
|
import { writeFile as writeFile3, mkdir as mkdir3, unlink as unlink2 } from "fs/promises";
|
|
4954
|
-
import { join as
|
|
5042
|
+
import { join as join5, dirname as dirname4 } from "path";
|
|
4955
5043
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
4956
5044
|
import matter from "gray-matter";
|
|
4957
5045
|
var __bundleDir2 = dirname4(fileURLToPath3(import.meta.url));
|
|
4958
|
-
var DEFAULTS_DIR2 =
|
|
4959
|
-
var DEFAULTS_DIR_ALT2 =
|
|
5046
|
+
var DEFAULTS_DIR2 = join5(__bundleDir2, "defaults");
|
|
5047
|
+
var DEFAULTS_DIR_ALT2 = join5(__bundleDir2, "command-defaults");
|
|
4960
5048
|
var COMMAND_EXTENSION = ".command.md";
|
|
4961
5049
|
function getCommandsDir(configDir) {
|
|
4962
|
-
return
|
|
5050
|
+
return join5(configDir, "commands");
|
|
5051
|
+
}
|
|
5052
|
+
function getProjectCommandsDir(projectDir) {
|
|
5053
|
+
return join5(projectDir, ".openfox", "commands");
|
|
4963
5054
|
}
|
|
4964
5055
|
async function loadDefaultCommands() {
|
|
4965
5056
|
let defaults = await loadItemsFromDir(DEFAULTS_DIR2, {
|
|
@@ -4980,7 +5071,13 @@ async function loadUserCommands(configDir) {
|
|
|
4980
5071
|
logName: "command"
|
|
4981
5072
|
});
|
|
4982
5073
|
}
|
|
4983
|
-
async function
|
|
5074
|
+
async function loadProjectCommands(projectDir) {
|
|
5075
|
+
return loadItemsFromDir(getProjectCommandsDir(projectDir), {
|
|
5076
|
+
extension: COMMAND_EXTENSION,
|
|
5077
|
+
logName: "command"
|
|
5078
|
+
});
|
|
5079
|
+
}
|
|
5080
|
+
async function loadAllCommands(configDir, projectDir) {
|
|
4984
5081
|
const [defaultCommands, userCommands] = await Promise.all([loadDefaultCommands(), loadUserCommands(configDir)]);
|
|
4985
5082
|
const commandMap = /* @__PURE__ */ new Map();
|
|
4986
5083
|
for (const cmd of defaultCommands) {
|
|
@@ -4989,6 +5086,12 @@ async function loadAllCommands(configDir) {
|
|
|
4989
5086
|
for (const cmd of userCommands) {
|
|
4990
5087
|
commandMap.set(cmd.metadata.id, cmd);
|
|
4991
5088
|
}
|
|
5089
|
+
if (projectDir) {
|
|
5090
|
+
const projectCommands = await loadProjectCommands(projectDir);
|
|
5091
|
+
for (const cmd of projectCommands) {
|
|
5092
|
+
commandMap.set(cmd.metadata.id, cmd);
|
|
5093
|
+
}
|
|
5094
|
+
}
|
|
4992
5095
|
return Array.from(commandMap.values());
|
|
4993
5096
|
}
|
|
4994
5097
|
async function getDefaultCommandIds() {
|
|
@@ -4996,10 +5099,6 @@ async function getDefaultCommandIds() {
|
|
|
4996
5099
|
if (ids.length) return ids;
|
|
4997
5100
|
return getDefaultIds(DEFAULTS_DIR_ALT2, COMMAND_EXTENSION);
|
|
4998
5101
|
}
|
|
4999
|
-
async function getDefaultCommandContent(commandId) {
|
|
5000
|
-
const defaults = await loadDefaultCommands();
|
|
5001
|
-
return defaults.find((c) => c.metadata.id === commandId) ?? null;
|
|
5002
|
-
}
|
|
5003
5102
|
async function isDefaultCommand(commandId) {
|
|
5004
5103
|
const defaultIds = await getDefaultCommandIds();
|
|
5005
5104
|
return defaultIds.includes(commandId);
|
|
@@ -5007,24 +5106,38 @@ async function isDefaultCommand(commandId) {
|
|
|
5007
5106
|
function findCommandById(commandId, commands) {
|
|
5008
5107
|
return commands.find((c) => c.metadata.id === commandId);
|
|
5009
5108
|
}
|
|
5010
|
-
async function commandExists(configDir, commandId) {
|
|
5011
|
-
|
|
5109
|
+
async function commandExists(configDir, commandId, projectDir) {
|
|
5110
|
+
if (await pathExists(join5(getCommandsDir(configDir), `${commandId}${COMMAND_EXTENSION}`))) return true;
|
|
5111
|
+
if (projectDir && await pathExists(join5(getProjectCommandsDir(projectDir), `${commandId}${COMMAND_EXTENSION}`)))
|
|
5112
|
+
return true;
|
|
5113
|
+
return false;
|
|
5012
5114
|
}
|
|
5013
5115
|
async function saveCommand(configDir, command) {
|
|
5014
5116
|
const commandsDir = getCommandsDir(configDir);
|
|
5015
5117
|
if (!await pathExists(commandsDir)) {
|
|
5016
5118
|
await mkdir3(commandsDir, { recursive: true });
|
|
5017
5119
|
}
|
|
5018
|
-
const filePath =
|
|
5120
|
+
const filePath = join5(commandsDir, `${command.metadata.id}${COMMAND_EXTENSION}`);
|
|
5019
5121
|
const content = matter.stringify(command.prompt, command.metadata);
|
|
5020
5122
|
await writeFile3(filePath, content, "utf-8");
|
|
5021
5123
|
}
|
|
5124
|
+
async function saveCommandToProject(projectDir, command) {
|
|
5125
|
+
await saveItemToDir(
|
|
5126
|
+
getProjectCommandsDir(projectDir),
|
|
5127
|
+
command,
|
|
5128
|
+
COMMAND_EXTENSION,
|
|
5129
|
+
(c) => matter.stringify(c.prompt, c.metadata)
|
|
5130
|
+
);
|
|
5131
|
+
}
|
|
5132
|
+
async function deleteProjectCommand(projectDir, commandId) {
|
|
5133
|
+
return deleteItemFromDir(getProjectCommandsDir(projectDir), commandId, COMMAND_EXTENSION);
|
|
5134
|
+
}
|
|
5022
5135
|
async function deleteCommand(configDir, commandId) {
|
|
5023
5136
|
const isDefault = await isDefaultCommand(commandId);
|
|
5024
5137
|
if (isDefault) {
|
|
5025
5138
|
return { success: false, reason: "Cannot delete built-in defaults" };
|
|
5026
5139
|
}
|
|
5027
|
-
const filePath =
|
|
5140
|
+
const filePath = join5(getCommandsDir(configDir), `${commandId}${COMMAND_EXTENSION}`);
|
|
5028
5141
|
try {
|
|
5029
5142
|
await unlink2(filePath);
|
|
5030
5143
|
return { success: true };
|
|
@@ -5034,292 +5147,106 @@ async function deleteCommand(configDir, commandId) {
|
|
|
5034
5147
|
}
|
|
5035
5148
|
|
|
5036
5149
|
// src/server/routes/commands.ts
|
|
5037
|
-
|
|
5038
|
-
|
|
5039
|
-
|
|
5040
|
-
|
|
5041
|
-
|
|
5042
|
-
|
|
5043
|
-
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
5050
|
-
|
|
5051
|
-
|
|
5052
|
-
|
|
5053
|
-
|
|
5054
|
-
|
|
5055
|
-
|
|
5056
|
-
|
|
5057
|
-
const ids = await getDefaultCommandIds();
|
|
5058
|
-
res.json({ ids });
|
|
5059
|
-
});
|
|
5060
|
-
router.get("/:id", async (req, res) => {
|
|
5061
|
-
const { id } = req.params;
|
|
5062
|
-
const commands = await loadAllCommands(configDir);
|
|
5063
|
-
const command = findCommandById(id, commands);
|
|
5064
|
-
if (!command) {
|
|
5065
|
-
return res.status(404).json({ error: "Command not found" });
|
|
5066
|
-
}
|
|
5067
|
-
res.json(command);
|
|
5068
|
-
});
|
|
5069
|
-
router.post("/", async (req, res) => {
|
|
5070
|
-
const body = req.body;
|
|
5071
|
-
if (!body.metadata?.id || !body.metadata?.name || !body.prompt) {
|
|
5072
|
-
return res.status(400).json({ error: "Missing required fields: metadata.id, metadata.name, prompt" });
|
|
5073
|
-
}
|
|
5074
|
-
if (!/^[a-z0-9-]+$/.test(body.metadata.id)) {
|
|
5075
|
-
return res.status(400).json({ error: "Command ID must be lowercase alphanumeric with hyphens only" });
|
|
5076
|
-
}
|
|
5077
|
-
const exists = await commandExists(configDir, body.metadata.id);
|
|
5078
|
-
if (exists) {
|
|
5079
|
-
return res.status(409).json({ error: "A command with this ID already exists" });
|
|
5080
|
-
}
|
|
5081
|
-
await saveCommand(configDir, body);
|
|
5082
|
-
res.status(201).json(body);
|
|
5083
|
-
});
|
|
5084
|
-
router.put("/:id", async (req, res) => {
|
|
5085
|
-
const { id } = req.params;
|
|
5086
|
-
const commands = await loadAllCommands(configDir);
|
|
5087
|
-
const existing = findCommandById(id, commands);
|
|
5088
|
-
if (!existing) {
|
|
5089
|
-
return res.status(404).json({ error: "Command not found" });
|
|
5090
|
-
}
|
|
5091
|
-
const body = req.body;
|
|
5092
|
-
const updated = {
|
|
5093
|
-
metadata: { ...existing.metadata, ...body.metadata, id },
|
|
5094
|
-
prompt: body.prompt ?? existing.prompt
|
|
5095
|
-
};
|
|
5096
|
-
await saveCommand(configDir, updated);
|
|
5097
|
-
res.json(updated);
|
|
5098
|
-
});
|
|
5099
|
-
router.delete("/:id", async (req, res) => {
|
|
5100
|
-
const { id } = req.params;
|
|
5101
|
-
const result = await deleteCommand(configDir, id);
|
|
5102
|
-
if (!result.success) {
|
|
5103
|
-
return res.status(403).json({ error: result.reason ?? "Cannot delete this command" });
|
|
5104
|
-
}
|
|
5105
|
-
res.json({ success: true });
|
|
5106
|
-
});
|
|
5107
|
-
router.post("/:id/duplicate", async (req, res) => {
|
|
5108
|
-
const { id } = req.params;
|
|
5109
|
-
const defaults = await loadDefaultCommands();
|
|
5110
|
-
const userItems = await loadUserCommands(configDir);
|
|
5111
|
-
const source = defaults.find((c) => c.metadata.id === id) ?? userItems.find((c) => c.metadata.id === id);
|
|
5112
|
-
if (!source) {
|
|
5113
|
-
return res.status(404).json({ error: "Command not found" });
|
|
5114
|
-
}
|
|
5115
|
-
const newId = `${id}-copy-${Date.now()}`;
|
|
5116
|
-
const duplicated = {
|
|
5117
|
-
metadata: { ...source.metadata, id: newId, name: `${source.metadata.name} (copy)` },
|
|
5118
|
-
prompt: source.prompt
|
|
5119
|
-
};
|
|
5120
|
-
await saveCommand(configDir, duplicated);
|
|
5121
|
-
res.status(201).json(duplicated);
|
|
5122
|
-
});
|
|
5123
|
-
return router;
|
|
5150
|
+
var config2 = {
|
|
5151
|
+
dirName: "commands",
|
|
5152
|
+
ext: ".command.md",
|
|
5153
|
+
loadDefaults: loadDefaultCommands,
|
|
5154
|
+
loadUser: loadUserCommands,
|
|
5155
|
+
loadProject: loadProjectCommands,
|
|
5156
|
+
loadAll: loadAllCommands,
|
|
5157
|
+
findById: findCommandById,
|
|
5158
|
+
save: saveCommand,
|
|
5159
|
+
saveToProject: saveCommandToProject,
|
|
5160
|
+
delete: deleteCommand,
|
|
5161
|
+
deleteProject: deleteProjectCommand,
|
|
5162
|
+
exists: commandExists,
|
|
5163
|
+
isDefault: isDefaultCommand,
|
|
5164
|
+
getDefaultIds: getDefaultCommandIds,
|
|
5165
|
+
validateCreate: validateNameIdPrompt,
|
|
5166
|
+
mapToResponse: (c) => c.metadata
|
|
5167
|
+
};
|
|
5168
|
+
function createCommandRoutes(configDir, projectDir) {
|
|
5169
|
+
return createCrudRoutes(config2, configDir, projectDir);
|
|
5124
5170
|
}
|
|
5125
5171
|
|
|
5126
5172
|
// src/server/routes/agents.ts
|
|
5127
|
-
|
|
5128
|
-
|
|
5129
|
-
|
|
5130
|
-
|
|
5131
|
-
|
|
5132
|
-
|
|
5133
|
-
|
|
5134
|
-
|
|
5135
|
-
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
|
|
5140
|
-
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
}
|
|
5147
|
-
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
|
|
5151
|
-
router.get("/:id", async (req, res) => {
|
|
5152
|
-
const { id } = req.params;
|
|
5153
|
-
const agents = await loadAllAgents(configDir);
|
|
5154
|
-
const agent = findAgentById(id, agents);
|
|
5155
|
-
if (!agent) {
|
|
5156
|
-
return res.status(404).json({ error: "Agent not found" });
|
|
5157
|
-
}
|
|
5158
|
-
res.json(agent);
|
|
5159
|
-
});
|
|
5160
|
-
router.post("/", async (req, res) => {
|
|
5161
|
-
const body = req.body;
|
|
5162
|
-
if (!body?.metadata?.id || !body?.prompt) {
|
|
5163
|
-
return res.status(400).json({ error: "Missing required fields: metadata.id, prompt" });
|
|
5164
|
-
}
|
|
5165
|
-
const exists = await agentExists(configDir, body.metadata.id);
|
|
5166
|
-
if (exists) {
|
|
5167
|
-
return res.status(409).json({ error: "An agent with this ID already exists" });
|
|
5168
|
-
}
|
|
5169
|
-
await saveAgent(configDir, body);
|
|
5170
|
-
res.status(201).json(body);
|
|
5171
|
-
});
|
|
5172
|
-
router.put("/:id", async (req, res) => {
|
|
5173
|
-
const { id } = req.params;
|
|
5174
|
-
if (!id) {
|
|
5175
|
-
return res.status(400).json({ error: "Missing agent ID" });
|
|
5176
|
-
}
|
|
5177
|
-
const body = req.body;
|
|
5178
|
-
const agents = await loadAllAgents(configDir);
|
|
5179
|
-
const existing = findAgentById(id, agents);
|
|
5180
|
-
if (!existing) {
|
|
5181
|
-
return res.status(404).json({ error: "Agent not found" });
|
|
5182
|
-
}
|
|
5183
|
-
const updated = {
|
|
5184
|
-
metadata: { ...existing.metadata, ...body.metadata, id },
|
|
5185
|
-
prompt: body.prompt ?? existing.prompt
|
|
5186
|
-
};
|
|
5187
|
-
await saveAgent(configDir, updated);
|
|
5188
|
-
res.json(updated);
|
|
5189
|
-
});
|
|
5190
|
-
router.delete("/:id", async (req, res) => {
|
|
5191
|
-
const { id } = req.params;
|
|
5192
|
-
const result = await deleteAgent(configDir, id);
|
|
5193
|
-
if (!result.success) {
|
|
5194
|
-
return res.status(403).json({ error: result.reason ?? "Cannot delete this agent" });
|
|
5195
|
-
}
|
|
5196
|
-
res.json({ success: true });
|
|
5197
|
-
});
|
|
5198
|
-
router.post("/:id/duplicate", async (req, res) => {
|
|
5199
|
-
const { id } = req.params;
|
|
5200
|
-
const defaults = await loadDefaultAgents();
|
|
5201
|
-
const userItems = await loadUserAgents(configDir);
|
|
5202
|
-
const source = defaults.find((a) => a.metadata.id === id) ?? userItems.find((a) => a.metadata.id === id);
|
|
5203
|
-
if (!source) {
|
|
5204
|
-
return res.status(404).json({ error: "Agent not found" });
|
|
5205
|
-
}
|
|
5206
|
-
const newId = `${id}-copy-${Date.now()}`;
|
|
5207
|
-
const duplicated = {
|
|
5208
|
-
metadata: { ...source.metadata, id: newId, name: `${source.metadata.name} (copy)` },
|
|
5209
|
-
prompt: source.prompt
|
|
5210
|
-
};
|
|
5211
|
-
await saveAgent(configDir, duplicated);
|
|
5212
|
-
res.status(201).json(duplicated);
|
|
5213
|
-
});
|
|
5214
|
-
return router;
|
|
5173
|
+
var config3 = {
|
|
5174
|
+
dirName: "agents",
|
|
5175
|
+
ext: ".agent.md",
|
|
5176
|
+
loadDefaults: loadDefaultAgents,
|
|
5177
|
+
loadUser: loadUserAgents,
|
|
5178
|
+
loadProject: loadProjectAgents,
|
|
5179
|
+
loadAll: loadAllAgents,
|
|
5180
|
+
findById: findAgentById,
|
|
5181
|
+
save: saveAgent,
|
|
5182
|
+
saveToProject: saveAgentToProject,
|
|
5183
|
+
delete: deleteAgent,
|
|
5184
|
+
deleteProject: deleteProjectAgent,
|
|
5185
|
+
exists: agentExists,
|
|
5186
|
+
isDefault: isDefaultAgent,
|
|
5187
|
+
getDefaultIds: getDefaultAgentIds,
|
|
5188
|
+
validateCreate: (body) => {
|
|
5189
|
+
const meta = body["metadata"];
|
|
5190
|
+
if (!meta?.["id"] || !body["prompt"]) return "Missing required fields: metadata.id, prompt";
|
|
5191
|
+
return null;
|
|
5192
|
+
},
|
|
5193
|
+
mapToResponse: (a) => a.metadata
|
|
5194
|
+
};
|
|
5195
|
+
function createAgentRoutes(configDir, projectDir) {
|
|
5196
|
+
return createCrudRoutes(config3, configDir, projectDir);
|
|
5215
5197
|
}
|
|
5216
5198
|
|
|
5217
5199
|
// src/server/routes/workflows.ts
|
|
5218
|
-
import
|
|
5219
|
-
function createWorkflowRoutes(configDir,
|
|
5220
|
-
const
|
|
5221
|
-
|
|
5222
|
-
|
|
5223
|
-
|
|
5224
|
-
|
|
5225
|
-
|
|
5226
|
-
|
|
5227
|
-
|
|
5228
|
-
|
|
5229
|
-
|
|
5230
|
-
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
|
|
5238
|
-
return
|
|
5239
|
-
}
|
|
5240
|
-
|
|
5241
|
-
|
|
5242
|
-
|
|
5243
|
-
|
|
5244
|
-
|
|
5245
|
-
|
|
5246
|
-
|
|
5247
|
-
|
|
5248
|
-
|
|
5249
|
-
const workflow = findWorkflowById(id, workflows);
|
|
5250
|
-
if (!workflow) {
|
|
5251
|
-
return res.status(404).json({ error: "Workflow not found" });
|
|
5252
|
-
}
|
|
5253
|
-
res.json(workflow);
|
|
5254
|
-
});
|
|
5255
|
-
router.post("/", async (req, res) => {
|
|
5256
|
-
const body = req.body;
|
|
5257
|
-
if (!body?.metadata?.id || !body?.steps?.length) {
|
|
5258
|
-
return res.status(400).json({ error: "Missing required fields: metadata.id, steps" });
|
|
5259
|
-
}
|
|
5260
|
-
const exists = await workflowExists(configDir, body.metadata.id);
|
|
5261
|
-
if (exists) {
|
|
5262
|
-
return res.status(409).json({ error: "A workflow with this ID already exists" });
|
|
5263
|
-
}
|
|
5264
|
-
await saveWorkflow(configDir, body);
|
|
5265
|
-
res.status(201).json(body);
|
|
5266
|
-
});
|
|
5267
|
-
router.put("/:id", async (req, res) => {
|
|
5268
|
-
const { id } = req.params;
|
|
5269
|
-
const workflows = await loadAllWorkflows(configDir);
|
|
5270
|
-
const existing = findWorkflowById(id, workflows);
|
|
5271
|
-
if (!existing) {
|
|
5272
|
-
return res.status(404).json({ error: "Workflow not found" });
|
|
5273
|
-
}
|
|
5274
|
-
const body = req.body;
|
|
5275
|
-
const updated = {
|
|
5276
|
-
...body,
|
|
5277
|
-
metadata: { ...body.metadata, id }
|
|
5278
|
-
};
|
|
5279
|
-
await saveWorkflow(configDir, updated);
|
|
5280
|
-
res.json(updated);
|
|
5281
|
-
});
|
|
5282
|
-
router.delete("/:id", async (req, res) => {
|
|
5283
|
-
const { id } = req.params;
|
|
5284
|
-
const result = await deleteWorkflow(configDir, id);
|
|
5285
|
-
if (!result.success) {
|
|
5286
|
-
return res.status(403).json({ error: result.reason ?? "Cannot delete this workflow" });
|
|
5287
|
-
}
|
|
5288
|
-
res.json({ success: true });
|
|
5289
|
-
});
|
|
5290
|
-
router.post("/:id/duplicate", async (req, res) => {
|
|
5291
|
-
const { id } = req.params;
|
|
5292
|
-
const defaults = await loadDefaultWorkflows();
|
|
5293
|
-
const userItems = await loadUserWorkflows(configDir);
|
|
5294
|
-
const source = defaults.find((w) => w.metadata.id === id) ?? userItems.find((w) => w.metadata.id === id);
|
|
5295
|
-
if (!source) {
|
|
5296
|
-
return res.status(404).json({ error: "Workflow not found" });
|
|
5200
|
+
import "express";
|
|
5201
|
+
function createWorkflowRoutes(configDir, config4, projectDir) {
|
|
5202
|
+
const crudConfig = {
|
|
5203
|
+
dirName: "workflows",
|
|
5204
|
+
ext: ".workflow.json",
|
|
5205
|
+
loadDefaults: loadDefaultWorkflows,
|
|
5206
|
+
loadUser: loadUserWorkflows,
|
|
5207
|
+
loadProject: loadProjectWorkflows,
|
|
5208
|
+
loadAll: loadAllWorkflows,
|
|
5209
|
+
findById: findWorkflowById,
|
|
5210
|
+
save: saveWorkflow,
|
|
5211
|
+
saveToProject: saveWorkflowToProject,
|
|
5212
|
+
delete: deleteWorkflow,
|
|
5213
|
+
deleteProject: deleteProjectWorkflow,
|
|
5214
|
+
exists: workflowExists,
|
|
5215
|
+
isDefault: isDefaultWorkflow,
|
|
5216
|
+
getDefaultIds: getDefaultWorkflowIds,
|
|
5217
|
+
validateCreate: (body) => {
|
|
5218
|
+
const steps = body["steps"];
|
|
5219
|
+
if (!Array.isArray(steps) || steps.length === 0) return "Missing required fields: metadata.id, steps";
|
|
5220
|
+
return null;
|
|
5221
|
+
},
|
|
5222
|
+
mapToResponse: (w) => ({
|
|
5223
|
+
...w.metadata,
|
|
5224
|
+
startCondition: w.startCondition
|
|
5225
|
+
}),
|
|
5226
|
+
extraGetData: () => Promise.resolve({ activeWorkflowId: config4.activeWorkflowId ?? "default" }),
|
|
5227
|
+
extraRoutes: (router) => {
|
|
5228
|
+
router.get("/template-variables", (_req, res) => {
|
|
5229
|
+
res.json({ variables: TEMPLATE_VARIABLES });
|
|
5230
|
+
});
|
|
5297
5231
|
}
|
|
5298
|
-
|
|
5299
|
-
|
|
5300
|
-
...source,
|
|
5301
|
-
metadata: { ...source.metadata, id: newId, name: `${source.metadata.name} (copy)` }
|
|
5302
|
-
};
|
|
5303
|
-
await saveWorkflow(configDir, duplicated);
|
|
5304
|
-
res.status(201).json(duplicated);
|
|
5305
|
-
});
|
|
5306
|
-
return router;
|
|
5232
|
+
};
|
|
5233
|
+
return createCrudRoutes(crudConfig, configDir, projectDir);
|
|
5307
5234
|
}
|
|
5308
5235
|
|
|
5309
5236
|
// src/server/routes/dev-server.ts
|
|
5310
|
-
import { Router as
|
|
5237
|
+
import { Router as Router3 } from "express";
|
|
5311
5238
|
function createDevServerRoutes() {
|
|
5312
|
-
const router =
|
|
5239
|
+
const router = Router3();
|
|
5313
5240
|
router.get("/", async (req, res) => {
|
|
5314
5241
|
const workdir = req.query["workdir"];
|
|
5315
5242
|
if (!workdir) return res.status(400).json({ error: "workdir required" });
|
|
5316
5243
|
const status = devServerManager.getStatus(workdir);
|
|
5317
5244
|
if (!status.config) {
|
|
5318
|
-
const
|
|
5319
|
-
if (
|
|
5320
|
-
status.config =
|
|
5321
|
-
status.url =
|
|
5322
|
-
status.hotReload =
|
|
5245
|
+
const config4 = await devServerManager.loadConfig(workdir);
|
|
5246
|
+
if (config4) {
|
|
5247
|
+
status.config = config4;
|
|
5248
|
+
status.url = config4.url;
|
|
5249
|
+
status.hotReload = config4.hotReload;
|
|
5323
5250
|
}
|
|
5324
5251
|
}
|
|
5325
5252
|
res.json(status);
|
|
@@ -5365,8 +5292,8 @@ function createDevServerRoutes() {
|
|
|
5365
5292
|
router.get("/config", async (req, res) => {
|
|
5366
5293
|
const workdir = req.query["workdir"];
|
|
5367
5294
|
if (!workdir) return res.status(400).json({ error: "workdir required" });
|
|
5368
|
-
const
|
|
5369
|
-
res.json({ config });
|
|
5295
|
+
const config4 = await devServerManager.loadConfig(workdir);
|
|
5296
|
+
res.json({ config: config4 });
|
|
5370
5297
|
});
|
|
5371
5298
|
router.post("/config", async (req, res) => {
|
|
5372
5299
|
const workdir = req.query["workdir"];
|
|
@@ -5376,9 +5303,9 @@ function createDevServerRoutes() {
|
|
|
5376
5303
|
return res.status(400).json({ error: "command and url are required" });
|
|
5377
5304
|
}
|
|
5378
5305
|
try {
|
|
5379
|
-
const
|
|
5380
|
-
await devServerManager.saveConfig(workdir,
|
|
5381
|
-
res.json({ config });
|
|
5306
|
+
const config4 = { command, url, hotReload: hotReload ?? false, disableInspect: disableInspect ?? false };
|
|
5307
|
+
await devServerManager.saveConfig(workdir, config4);
|
|
5308
|
+
res.json({ config: config4 });
|
|
5382
5309
|
} catch (err) {
|
|
5383
5310
|
res.status(500).json({ error: err instanceof Error ? err.message : "Failed to save config" });
|
|
5384
5311
|
}
|
|
@@ -5387,9 +5314,9 @@ function createDevServerRoutes() {
|
|
|
5387
5314
|
}
|
|
5388
5315
|
|
|
5389
5316
|
// src/server/routes/terminals.ts
|
|
5390
|
-
import { Router as
|
|
5317
|
+
import { Router as Router4 } from "express";
|
|
5391
5318
|
function createTerminalRoutes() {
|
|
5392
|
-
const router =
|
|
5319
|
+
const router = Router4();
|
|
5393
5320
|
router.get("/", (req, res) => {
|
|
5394
5321
|
const projectId = req.query["projectId"];
|
|
5395
5322
|
const sessions = projectId ? terminalManager.getByProject(projectId) : [];
|
|
@@ -5428,16 +5355,16 @@ function createTerminalRoutes() {
|
|
|
5428
5355
|
}
|
|
5429
5356
|
|
|
5430
5357
|
// src/server/routes/auto-update.ts
|
|
5431
|
-
import { Router as
|
|
5358
|
+
import { Router as Router5 } from "express";
|
|
5432
5359
|
import { spawn as spawn4 } from "child_process";
|
|
5433
5360
|
|
|
5434
5361
|
// src/constants.ts
|
|
5435
|
-
var VERSION = "1.6.
|
|
5362
|
+
var VERSION = "1.6.93";
|
|
5436
5363
|
|
|
5437
5364
|
// src/server/routes/auto-update.ts
|
|
5438
5365
|
var updateInProgress = false;
|
|
5439
5366
|
function createAutoUpdateRoutes(options = {}) {
|
|
5440
|
-
const router =
|
|
5367
|
+
const router = Router5();
|
|
5441
5368
|
router.get("/check", async (req, res) => {
|
|
5442
5369
|
const isTest = req.query["test"] === "1";
|
|
5443
5370
|
const current = VERSION;
|
|
@@ -5518,14 +5445,14 @@ function createAutoUpdateRoutes(options = {}) {
|
|
|
5518
5445
|
|
|
5519
5446
|
// src/server/index.ts
|
|
5520
5447
|
var __dirname2 = dirname5(fileURLToPath4(import.meta.url));
|
|
5521
|
-
async function createServerHandle(
|
|
5522
|
-
setRuntimeConfig(
|
|
5523
|
-
setLogLevel(
|
|
5448
|
+
async function createServerHandle(config4) {
|
|
5449
|
+
setRuntimeConfig(config4);
|
|
5450
|
+
setLogLevel(config4.logging?.level ?? void 0, config4.mode);
|
|
5524
5451
|
await loadServerAuthConfig();
|
|
5525
|
-
const db = initDatabase(
|
|
5452
|
+
const db = initDatabase(config4);
|
|
5526
5453
|
initEventStore(db);
|
|
5527
|
-
const configDir = getGlobalConfigDir(
|
|
5528
|
-
const providerManager = createProviderManager(
|
|
5454
|
+
const configDir = getGlobalConfigDir(config4.mode ?? "production");
|
|
5455
|
+
const providerManager = createProviderManager(config4);
|
|
5529
5456
|
const sessionManager = new SessionManager(providerManager);
|
|
5530
5457
|
devServerManager.setSessionManager(sessionManager);
|
|
5531
5458
|
const useMock = process.env["OPENFOX_MOCK_LLM"] === "true";
|
|
@@ -5538,20 +5465,20 @@ async function createServerHandle(config) {
|
|
|
5538
5465
|
const llmClient = getLLMClient();
|
|
5539
5466
|
let backend;
|
|
5540
5467
|
const useMock2 = process.env["OPENFOX_MOCK_LLM"] === "true";
|
|
5541
|
-
if (
|
|
5542
|
-
backend = await detectBackend(
|
|
5468
|
+
if (config4.llm.backend === "auto") {
|
|
5469
|
+
backend = await detectBackend(config4.llm.baseUrl, void 0, useMock2);
|
|
5543
5470
|
llmClient.setBackend(backend);
|
|
5544
5471
|
if (!useMock2) {
|
|
5545
5472
|
logger.info("Auto-detected LLM backend", { backend: getBackendDisplayName(backend) });
|
|
5546
5473
|
}
|
|
5547
5474
|
} else {
|
|
5548
|
-
backend =
|
|
5475
|
+
backend = config4.llm.backend;
|
|
5549
5476
|
llmClient.setBackend(backend);
|
|
5550
5477
|
if (!useMock2) {
|
|
5551
5478
|
logger.info("Using configured LLM backend", { backend: getBackendDisplayName(backend) });
|
|
5552
5479
|
}
|
|
5553
5480
|
}
|
|
5554
|
-
const detected = await detectModel(
|
|
5481
|
+
const detected = await detectModel(config4.llm.baseUrl);
|
|
5555
5482
|
if (detected) {
|
|
5556
5483
|
llmClient.setModel(detected);
|
|
5557
5484
|
if (!useMock2) {
|
|
@@ -5559,7 +5486,7 @@ async function createServerHandle(config) {
|
|
|
5559
5486
|
}
|
|
5560
5487
|
} else {
|
|
5561
5488
|
if (!useMock2) {
|
|
5562
|
-
logger.warn("Could not auto-detect model, using config", { model:
|
|
5489
|
+
logger.warn("Could not auto-detect model, using config", { model: config4.llm.model });
|
|
5563
5490
|
}
|
|
5564
5491
|
}
|
|
5565
5492
|
const activeProvider = providerManager.getActiveProvider();
|
|
@@ -5729,7 +5656,7 @@ async function createServerHandle(config) {
|
|
|
5729
5656
|
res.json({ project });
|
|
5730
5657
|
});
|
|
5731
5658
|
app.get("/api/sessions", async (req, res) => {
|
|
5732
|
-
const { getRecentUserPromptsForSession } = await import("./events-
|
|
5659
|
+
const { getRecentUserPromptsForSession } = await import("./events-K6AYMXFT.js");
|
|
5733
5660
|
const projectId = req.query["projectId"];
|
|
5734
5661
|
const limit = Math.min(parseInt(req.query["limit"]) || 20, 100);
|
|
5735
5662
|
const offset = parseInt(req.query["offset"]) || 0;
|
|
@@ -5757,12 +5684,12 @@ async function createServerHandle(config) {
|
|
|
5757
5684
|
if (!project) {
|
|
5758
5685
|
return res.status(404).json({ error: "Project not found" });
|
|
5759
5686
|
}
|
|
5760
|
-
const { providerId, model } = parseDefaultModelSelection(
|
|
5687
|
+
const { providerId, model } = parseDefaultModelSelection(config4.defaultModelSelection);
|
|
5761
5688
|
const session = sessionManager.createSession(projectId, title, providerId ?? null, model ?? null);
|
|
5762
5689
|
res.status(201).json({ session });
|
|
5763
5690
|
});
|
|
5764
5691
|
app.get("/api/sessions/:id", async (req, res) => {
|
|
5765
|
-
const { getEventStore: getEventStore2 } = await import("./events-
|
|
5692
|
+
const { getEventStore: getEventStore2 } = await import("./events-K6AYMXFT.js");
|
|
5766
5693
|
const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2 } = await import("./folding-4VHGQE6Y.js");
|
|
5767
5694
|
const session = sessionManager.getSession(req.params.id);
|
|
5768
5695
|
if (!session) {
|
|
@@ -5793,7 +5720,7 @@ async function createServerHandle(config) {
|
|
|
5793
5720
|
res.json({ success: true });
|
|
5794
5721
|
});
|
|
5795
5722
|
app.post("/api/sessions/:id/provider", async (req, res) => {
|
|
5796
|
-
const { getEventStore: getEventStore2 } = await import("./events-
|
|
5723
|
+
const { getEventStore: getEventStore2 } = await import("./events-K6AYMXFT.js");
|
|
5797
5724
|
const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2 } = await import("./folding-4VHGQE6Y.js");
|
|
5798
5725
|
const sessionId = req.params.id;
|
|
5799
5726
|
const session = sessionManager.getSession(sessionId);
|
|
@@ -5805,11 +5732,11 @@ async function createServerHandle(config) {
|
|
|
5805
5732
|
return res.status(400).json({ error: "providerId is required" });
|
|
5806
5733
|
}
|
|
5807
5734
|
sessionManager.setSessionProvider(sessionId, providerId, model ?? "auto");
|
|
5808
|
-
const { loadGlobalConfig, saveGlobalConfig, setDefaultModelSelection } = await import("./config-
|
|
5809
|
-
const globalConfig = await loadGlobalConfig(
|
|
5735
|
+
const { loadGlobalConfig, saveGlobalConfig, setDefaultModelSelection } = await import("./config-TSGOFNJW.js");
|
|
5736
|
+
const globalConfig = await loadGlobalConfig(config4.mode ?? "production");
|
|
5810
5737
|
const updatedConfig = setDefaultModelSelection(globalConfig, providerId, model ?? "auto");
|
|
5811
|
-
await saveGlobalConfig(
|
|
5812
|
-
|
|
5738
|
+
await saveGlobalConfig(config4.mode ?? "production", updatedConfig);
|
|
5739
|
+
config4.defaultModelSelection = updatedConfig.defaultModelSelection;
|
|
5813
5740
|
const contextState = sessionManager.getContextState(sessionId);
|
|
5814
5741
|
const eventStore = getEventStore2();
|
|
5815
5742
|
const events = eventStore.getEvents(sessionId);
|
|
@@ -5831,7 +5758,7 @@ async function createServerHandle(config) {
|
|
|
5831
5758
|
res.json({ success: true });
|
|
5832
5759
|
});
|
|
5833
5760
|
app.put("/api/sessions/:id/mode", async (req, res) => {
|
|
5834
|
-
const { getEventStore: getEventStore2 } = await import("./events-
|
|
5761
|
+
const { getEventStore: getEventStore2 } = await import("./events-K6AYMXFT.js");
|
|
5835
5762
|
const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2 } = await import("./folding-4VHGQE6Y.js");
|
|
5836
5763
|
const sessionId = req.params.id;
|
|
5837
5764
|
const session = sessionManager.getSession(sessionId);
|
|
@@ -5888,12 +5815,12 @@ async function createServerHandle(config) {
|
|
|
5888
5815
|
if (!callId || approved === void 0) {
|
|
5889
5816
|
return res.status(400).json({ error: "callId and approved are required" });
|
|
5890
5817
|
}
|
|
5891
|
-
const { providePathConfirmation } = await import("./tools-
|
|
5818
|
+
const { providePathConfirmation } = await import("./tools-U6I43EN4.js");
|
|
5892
5819
|
const result = providePathConfirmation(callId, approved, alwaysAllow);
|
|
5893
5820
|
if (!result.found) {
|
|
5894
5821
|
return res.status(404).json({ error: "No pending path confirmation with that ID" });
|
|
5895
5822
|
}
|
|
5896
|
-
const { getEventStore: getEventStore2 } = await import("./events-
|
|
5823
|
+
const { getEventStore: getEventStore2 } = await import("./events-K6AYMXFT.js");
|
|
5897
5824
|
const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2, foldPendingConfirmations: foldPendingConfirmations2 } = await import("./folding-4VHGQE6Y.js");
|
|
5898
5825
|
const { createSessionStateMessage: createSessionStateMessage2 } = await import("./protocol-QDSVJTRN.js");
|
|
5899
5826
|
const eventStore = getEventStore2();
|
|
@@ -5912,7 +5839,7 @@ async function createServerHandle(config) {
|
|
|
5912
5839
|
if (!callId || !answer) {
|
|
5913
5840
|
return res.status(400).json({ error: "callId and answer are required" });
|
|
5914
5841
|
}
|
|
5915
|
-
const { provideAnswer: provideAnswer2 } = await import("./tools-
|
|
5842
|
+
const { provideAnswer: provideAnswer2 } = await import("./tools-U6I43EN4.js");
|
|
5916
5843
|
const found = provideAnswer2(callId, answer);
|
|
5917
5844
|
if (!found) {
|
|
5918
5845
|
return res.status(404).json({ error: "No pending question with that ID" });
|
|
@@ -5948,14 +5875,14 @@ async function createServerHandle(config) {
|
|
|
5948
5875
|
if (!session) {
|
|
5949
5876
|
return res.status(404).json({ error: "Session not found" });
|
|
5950
5877
|
}
|
|
5951
|
-
const { stopSessionExecution } = await import("./chat-handler-
|
|
5952
|
-
const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-
|
|
5878
|
+
const { stopSessionExecution } = await import("./chat-handler-ROOMX2UY.js");
|
|
5879
|
+
const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-U6I43EN4.js");
|
|
5953
5880
|
stopSessionExecution(sessionId, sessionManager);
|
|
5954
5881
|
abortSession(sessionId);
|
|
5955
5882
|
cancelQuestionsForSession(sessionId, "Session stopped by user");
|
|
5956
5883
|
cancelPathConfirmationsForSession(sessionId, "Session stopped by user");
|
|
5957
5884
|
sessionManager.clearMessageQueue(sessionId);
|
|
5958
|
-
const eventStore = (await import("./events-
|
|
5885
|
+
const eventStore = (await import("./events-K6AYMXFT.js")).getEventStore();
|
|
5959
5886
|
eventStore.append(sessionId, { type: "running.changed", data: { isRunning: false } });
|
|
5960
5887
|
res.json({ success: true });
|
|
5961
5888
|
});
|
|
@@ -5969,7 +5896,7 @@ async function createServerHandle(config) {
|
|
|
5969
5896
|
if (typeof messageIndex !== "number" || messageIndex < 0) {
|
|
5970
5897
|
return res.status(400).json({ error: "messageIndex must be a non-negative number" });
|
|
5971
5898
|
}
|
|
5972
|
-
const { truncateSessionMessages } = await import("./events-
|
|
5899
|
+
const { truncateSessionMessages } = await import("./events-K6AYMXFT.js");
|
|
5973
5900
|
truncateSessionMessages(sessionId, messageIndex);
|
|
5974
5901
|
res.json({ success: true });
|
|
5975
5902
|
});
|
|
@@ -6021,14 +5948,14 @@ async function createServerHandle(config) {
|
|
|
6021
5948
|
let visionFallback;
|
|
6022
5949
|
let globalWorkdir;
|
|
6023
5950
|
try {
|
|
6024
|
-
const { loadGlobalConfig, getVisionFallback } = await import("./config-
|
|
6025
|
-
const globalConfig = await loadGlobalConfig(
|
|
5951
|
+
const { loadGlobalConfig, getVisionFallback } = await import("./config-TSGOFNJW.js");
|
|
5952
|
+
const globalConfig = await loadGlobalConfig(config4.mode ?? "production");
|
|
6026
5953
|
const fallback = getVisionFallback(globalConfig);
|
|
6027
5954
|
if (fallback) {
|
|
6028
5955
|
visionFallback = {
|
|
6029
5956
|
enabled: fallback.enabled ?? false,
|
|
6030
5957
|
url: fallback.url ?? "http://localhost:11434",
|
|
6031
|
-
model: fallback.model ?? "qwen3
|
|
5958
|
+
model: fallback.model ?? "qwen3.5:0.8b",
|
|
6032
5959
|
timeout: fallback.timeout ?? 120
|
|
6033
5960
|
};
|
|
6034
5961
|
}
|
|
@@ -6039,13 +5966,13 @@ async function createServerHandle(config) {
|
|
|
6039
5966
|
version: VERSION,
|
|
6040
5967
|
model: llmClient.getModel(),
|
|
6041
5968
|
maxContext: providerManager.getCurrentModelContext(),
|
|
6042
|
-
llmUrl: activeProvider?.url ??
|
|
5969
|
+
llmUrl: activeProvider?.url ?? config4.llm.baseUrl,
|
|
6043
5970
|
llmStatus: getLlmStatus(),
|
|
6044
5971
|
backend: llmClient.getBackend(),
|
|
6045
|
-
workdir: globalWorkdir ??
|
|
5972
|
+
workdir: globalWorkdir ?? config4.workdir,
|
|
6046
5973
|
providers: providerManager.getProviders(),
|
|
6047
5974
|
activeProviderId: providerManager.getActiveProviderId(),
|
|
6048
|
-
defaultModelSelection:
|
|
5975
|
+
defaultModelSelection: config4.defaultModelSelection,
|
|
6049
5976
|
visionFallback
|
|
6050
5977
|
});
|
|
6051
5978
|
});
|
|
@@ -6054,7 +5981,7 @@ async function createServerHandle(config) {
|
|
|
6054
5981
|
const currentModel = providerManager.getCurrentModel();
|
|
6055
5982
|
if (currentModel === "auto") {
|
|
6056
5983
|
const activeProvider = providerManager.getActiveProvider();
|
|
6057
|
-
const baseUrl = activeProvider?.url ??
|
|
5984
|
+
const baseUrl = activeProvider?.url ?? config4.llm.baseUrl;
|
|
6058
5985
|
const detected = await detectModel(baseUrl);
|
|
6059
5986
|
if (detected) {
|
|
6060
5987
|
llmClient.setModel(detected);
|
|
@@ -6100,8 +6027,8 @@ async function createServerHandle(config) {
|
|
|
6100
6027
|
return res.status(400).json({ error: "name, url, and backend are required" });
|
|
6101
6028
|
}
|
|
6102
6029
|
try {
|
|
6103
|
-
const { loadGlobalConfig, saveGlobalConfig, addProvider, setDefaultModelSelection } = await import("./config-
|
|
6104
|
-
const globalConfig = await loadGlobalConfig(
|
|
6030
|
+
const { loadGlobalConfig, saveGlobalConfig, addProvider, setDefaultModelSelection } = await import("./config-TSGOFNJW.js");
|
|
6031
|
+
const globalConfig = await loadGlobalConfig(config4.mode ?? "production");
|
|
6105
6032
|
const providerBackend = backend;
|
|
6106
6033
|
const configWithProvider = addProvider(globalConfig, {
|
|
6107
6034
|
name,
|
|
@@ -6116,7 +6043,7 @@ async function createServerHandle(config) {
|
|
|
6116
6043
|
configWithProvider.providers[configWithProvider.providers.length - 1].id,
|
|
6117
6044
|
model ?? "auto"
|
|
6118
6045
|
);
|
|
6119
|
-
await saveGlobalConfig(
|
|
6046
|
+
await saveGlobalConfig(config4.mode ?? "production", finalConfig);
|
|
6120
6047
|
providerManager.setProviders(finalConfig.providers, finalConfig.defaultModelSelection ?? void 0);
|
|
6121
6048
|
const newProvider = finalConfig.providers[finalConfig.providers.length - 1];
|
|
6122
6049
|
res.status(201).json({
|
|
@@ -6133,14 +6060,14 @@ async function createServerHandle(config) {
|
|
|
6133
6060
|
app.post("/api/init/config", async (req, res) => {
|
|
6134
6061
|
const { workdir, visionFallback } = req.body;
|
|
6135
6062
|
try {
|
|
6136
|
-
const { loadGlobalConfig, saveGlobalConfig } = await import("./config-
|
|
6137
|
-
const globalConfig = await loadGlobalConfig(
|
|
6063
|
+
const { loadGlobalConfig, saveGlobalConfig } = await import("./config-TSGOFNJW.js");
|
|
6064
|
+
const globalConfig = await loadGlobalConfig(config4.mode ?? "production");
|
|
6138
6065
|
const updatedConfig = {
|
|
6139
6066
|
...globalConfig,
|
|
6140
6067
|
workspace: workdir ? { workdir } : globalConfig.workspace,
|
|
6141
6068
|
visionFallback: visionFallback ?? globalConfig.visionFallback
|
|
6142
6069
|
};
|
|
6143
|
-
await saveGlobalConfig(
|
|
6070
|
+
await saveGlobalConfig(config4.mode ?? "production", updatedConfig);
|
|
6144
6071
|
res.json({ success: true });
|
|
6145
6072
|
} catch (error) {
|
|
6146
6073
|
res.status(500).json({
|
|
@@ -6161,10 +6088,10 @@ async function createServerHandle(config) {
|
|
|
6161
6088
|
});
|
|
6162
6089
|
app.delete("/api/providers/:id", async (req, res) => {
|
|
6163
6090
|
const { id } = req.params;
|
|
6164
|
-
const { loadGlobalConfig, saveGlobalConfig, removeProvider } = await import("./config-
|
|
6165
|
-
const globalConfig = await loadGlobalConfig(
|
|
6091
|
+
const { loadGlobalConfig, saveGlobalConfig, removeProvider } = await import("./config-TSGOFNJW.js");
|
|
6092
|
+
const globalConfig = await loadGlobalConfig(config4.mode ?? "production");
|
|
6166
6093
|
const updatedConfig = removeProvider(globalConfig, id);
|
|
6167
|
-
await saveGlobalConfig(
|
|
6094
|
+
await saveGlobalConfig(config4.mode ?? "production", updatedConfig);
|
|
6168
6095
|
providerManager.setProviders(updatedConfig.providers, updatedConfig.defaultModelSelection ?? void 0);
|
|
6169
6096
|
res.json({ success: true });
|
|
6170
6097
|
});
|
|
@@ -6181,10 +6108,10 @@ async function createServerHandle(config) {
|
|
|
6181
6108
|
return res.status(400).json({ error: result.error });
|
|
6182
6109
|
}
|
|
6183
6110
|
const llmClient = getLLMClient();
|
|
6184
|
-
const { loadGlobalConfig, saveGlobalConfig, setDefaultModelSelection } = await import("./config-
|
|
6185
|
-
const globalConfig = await loadGlobalConfig(
|
|
6111
|
+
const { loadGlobalConfig, saveGlobalConfig, setDefaultModelSelection } = await import("./config-TSGOFNJW.js");
|
|
6112
|
+
const globalConfig = await loadGlobalConfig(config4.mode ?? "production");
|
|
6186
6113
|
const updatedConfig = setDefaultModelSelection(globalConfig, id, llmClient.getModel());
|
|
6187
|
-
await saveGlobalConfig(
|
|
6114
|
+
await saveGlobalConfig(config4.mode ?? "production", updatedConfig);
|
|
6188
6115
|
res.json({
|
|
6189
6116
|
success: true,
|
|
6190
6117
|
activeProviderId: id,
|
|
@@ -6212,8 +6139,8 @@ async function createServerHandle(config) {
|
|
|
6212
6139
|
if (!result.success) {
|
|
6213
6140
|
return res.status(400).json({ error: result.error });
|
|
6214
6141
|
}
|
|
6215
|
-
const { loadGlobalConfig, saveGlobalConfig } = await import("./config-
|
|
6216
|
-
const globalConfig = await loadGlobalConfig(
|
|
6142
|
+
const { loadGlobalConfig, saveGlobalConfig } = await import("./config-TSGOFNJW.js");
|
|
6143
|
+
const globalConfig = await loadGlobalConfig(config4.mode ?? "production");
|
|
6217
6144
|
const updatedProviders = providerManager.getProviders();
|
|
6218
6145
|
const updatedConfig = {
|
|
6219
6146
|
...globalConfig,
|
|
@@ -6221,7 +6148,7 @@ async function createServerHandle(config) {
|
|
|
6221
6148
|
activeProviderId: providerManager.getActiveProviderId(),
|
|
6222
6149
|
defaultModelSelection: providerManager.getActiveProviderId() ? `${providerManager.getActiveProviderId()}/${providerManager.getCurrentModel()}` : void 0
|
|
6223
6150
|
};
|
|
6224
|
-
await saveGlobalConfig(
|
|
6151
|
+
await saveGlobalConfig(config4.mode ?? "production", updatedConfig);
|
|
6225
6152
|
let contextState = null;
|
|
6226
6153
|
const sessions = sessionManager.listSessions();
|
|
6227
6154
|
if (sessions.length > 0) {
|
|
@@ -6256,10 +6183,11 @@ async function createServerHandle(config) {
|
|
|
6256
6183
|
status: updatedProvider?.status ?? "unknown"
|
|
6257
6184
|
});
|
|
6258
6185
|
});
|
|
6259
|
-
|
|
6260
|
-
app.use("/api/
|
|
6261
|
-
app.use("/api/
|
|
6262
|
-
app.use("/api/
|
|
6186
|
+
const projectDir = config4.workdir;
|
|
6187
|
+
app.use("/api/skills", createSkillRoutes(configDir, projectDir));
|
|
6188
|
+
app.use("/api/commands", createCommandRoutes(configDir, projectDir));
|
|
6189
|
+
app.use("/api/agents", createAgentRoutes(configDir, projectDir));
|
|
6190
|
+
app.use("/api/workflows", createWorkflowRoutes(configDir, config4, projectDir));
|
|
6263
6191
|
app.use("/api/dev-server", createDevServerRoutes());
|
|
6264
6192
|
app.use("/api/terminals", createTerminalRoutes());
|
|
6265
6193
|
app.use(
|
|
@@ -6309,7 +6237,7 @@ async function createServerHandle(config) {
|
|
|
6309
6237
|
const entries = await import("fs/promises").then((m) => m.readdir(resolvedPath, { withFileTypes: true }));
|
|
6310
6238
|
const directories = entries.filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => ({
|
|
6311
6239
|
name: entry.name,
|
|
6312
|
-
path:
|
|
6240
|
+
path: join6(resolvedPath, entry.name)
|
|
6313
6241
|
})).sort((a, b) => a.name.localeCompare(b.name));
|
|
6314
6242
|
const parent = dirname5(resolvedPath);
|
|
6315
6243
|
const hasParent = parent !== resolvedPath;
|
|
@@ -6330,7 +6258,7 @@ async function createServerHandle(config) {
|
|
|
6330
6258
|
}
|
|
6331
6259
|
});
|
|
6332
6260
|
const webDir = resolve(__dirname2, "../../web");
|
|
6333
|
-
const isDev =
|
|
6261
|
+
const isDev = config4.mode === "development";
|
|
6334
6262
|
let viteServer;
|
|
6335
6263
|
if (isDev) {
|
|
6336
6264
|
logger.info("Dev mode: using Vite middleware");
|
|
@@ -6356,7 +6284,7 @@ async function createServerHandle(config) {
|
|
|
6356
6284
|
}
|
|
6357
6285
|
});
|
|
6358
6286
|
app.get("/fox.svg", (_req, res) => {
|
|
6359
|
-
readFile3(
|
|
6287
|
+
readFile3(join6(webDir, "fox.svg")).then((content) => {
|
|
6360
6288
|
res.set("Content-Type", "image/svg+xml");
|
|
6361
6289
|
res.send(content);
|
|
6362
6290
|
}).catch(() => {
|
|
@@ -6365,7 +6293,7 @@ async function createServerHandle(config) {
|
|
|
6365
6293
|
});
|
|
6366
6294
|
app.use(
|
|
6367
6295
|
"/sounds",
|
|
6368
|
-
express.static(
|
|
6296
|
+
express.static(join6(webDir, "public", "sounds"), {
|
|
6369
6297
|
setHeaders: (res) => {
|
|
6370
6298
|
res.set("Content-Type", "audio/mpeg");
|
|
6371
6299
|
}
|
|
@@ -6374,24 +6302,24 @@ async function createServerHandle(config) {
|
|
|
6374
6302
|
app.use("/__inspect__.js", (_req, res) => {
|
|
6375
6303
|
res.set("Access-Control-Allow-Origin", "*");
|
|
6376
6304
|
res.set("Content-Type", "application/javascript");
|
|
6377
|
-
readFile3(
|
|
6305
|
+
readFile3(join6(webDir, "public", "__inspect__.js")).then((content) => res.send(content)).catch(() => res.status(404).send("Not found"));
|
|
6378
6306
|
});
|
|
6379
6307
|
app.get("/*path", (req, res) => {
|
|
6380
6308
|
if (req.path.startsWith("/api/")) {
|
|
6381
6309
|
return;
|
|
6382
6310
|
}
|
|
6383
|
-
readFile3(
|
|
6311
|
+
readFile3(join6(webDir, "index.html"), "utf-8").then((indexHtml) => viteServer.transformIndexHtml(req.originalUrl, indexHtml)).then((transformed) => res.send(transformed)).catch((err) => {
|
|
6384
6312
|
logger.error("Error serving index.html", { error: err });
|
|
6385
6313
|
res.status(500).send("Server error");
|
|
6386
6314
|
});
|
|
6387
6315
|
});
|
|
6388
|
-
logger.info("Vite middleware ready", { port:
|
|
6316
|
+
logger.info("Vite middleware ready", { port: config4.server.port });
|
|
6389
6317
|
}
|
|
6390
6318
|
if (!isDev) {
|
|
6391
6319
|
const distWebDir = resolve(__dirname2, "web");
|
|
6392
6320
|
app.use(
|
|
6393
6321
|
"/assets",
|
|
6394
|
-
express.static(
|
|
6322
|
+
express.static(join6(distWebDir, "assets"), {
|
|
6395
6323
|
setHeaders: (res, filepath) => {
|
|
6396
6324
|
if (filepath.endsWith(".css")) {
|
|
6397
6325
|
res.set("Content-Type", "text/css");
|
|
@@ -6399,11 +6327,11 @@ async function createServerHandle(config) {
|
|
|
6399
6327
|
}
|
|
6400
6328
|
})
|
|
6401
6329
|
);
|
|
6402
|
-
app.use("/manifest.webmanifest", express.static(
|
|
6403
|
-
app.use("/registerSW.js", express.static(
|
|
6404
|
-
app.use("/sw.js", express.static(
|
|
6330
|
+
app.use("/manifest.webmanifest", express.static(join6(distWebDir, "manifest.webmanifest")));
|
|
6331
|
+
app.use("/registerSW.js", express.static(join6(distWebDir, "registerSW.js")));
|
|
6332
|
+
app.use("/sw.js", express.static(join6(distWebDir, "sw.js")));
|
|
6405
6333
|
app.get("/fox.svg", (_req, res) => {
|
|
6406
|
-
readFile3(
|
|
6334
|
+
readFile3(join6(distWebDir, "fox.svg")).then((content) => {
|
|
6407
6335
|
res.set("Content-Type", "image/svg+xml");
|
|
6408
6336
|
res.send(content);
|
|
6409
6337
|
}).catch(() => {
|
|
@@ -6412,7 +6340,7 @@ async function createServerHandle(config) {
|
|
|
6412
6340
|
});
|
|
6413
6341
|
app.use(
|
|
6414
6342
|
"/sounds",
|
|
6415
|
-
express.static(
|
|
6343
|
+
express.static(join6(distWebDir, "sounds"), {
|
|
6416
6344
|
setHeaders: (res) => {
|
|
6417
6345
|
res.set("Content-Type", "audio/mpeg");
|
|
6418
6346
|
}
|
|
@@ -6421,15 +6349,15 @@ async function createServerHandle(config) {
|
|
|
6421
6349
|
app.use("/__inspect__.js", (_req, res) => {
|
|
6422
6350
|
res.set("Access-Control-Allow-Origin", "*");
|
|
6423
6351
|
res.set("Content-Type", "application/javascript");
|
|
6424
|
-
readFile3(
|
|
6352
|
+
readFile3(join6(distWebDir, "__inspect__.js")).then((content) => res.send(content)).catch(() => res.status(404).send("Not found"));
|
|
6425
6353
|
});
|
|
6426
6354
|
app.use("/__inspect__.js", (_req, res) => {
|
|
6427
6355
|
res.set("Access-Control-Allow-Origin", "*");
|
|
6428
6356
|
res.set("Content-Type", "application/javascript");
|
|
6429
|
-
readFile3(
|
|
6357
|
+
readFile3(join6(distWebDir, "__inspect__.js")).then((content) => res.send(content)).catch(() => res.status(404).send("Not found"));
|
|
6430
6358
|
});
|
|
6431
6359
|
app.get("/", (_req, res) => {
|
|
6432
|
-
readFile3(
|
|
6360
|
+
readFile3(join6(distWebDir, "index.html"), "utf-8").then((content) => res.send(content)).catch(() => {
|
|
6433
6361
|
res.status(404).send("Web UI not built. Run `npm run build:web`");
|
|
6434
6362
|
});
|
|
6435
6363
|
});
|
|
@@ -6437,7 +6365,7 @@ async function createServerHandle(config) {
|
|
|
6437
6365
|
if (req.path.startsWith("/api/") || req.path.startsWith("/assets/") || req.path.startsWith("/sounds/") || req.path.startsWith("/manifest.webmanifest") || req.path.startsWith("/registerSW.js") || req.path.startsWith("/sw.js") || req.path === "/fox.svg") {
|
|
6438
6366
|
return;
|
|
6439
6367
|
}
|
|
6440
|
-
readFile3(
|
|
6368
|
+
readFile3(join6(distWebDir, "index.html"), "utf-8").then((content) => res.send(content)).catch(() => {
|
|
6441
6369
|
res.status(404).send("Web UI not built");
|
|
6442
6370
|
});
|
|
6443
6371
|
});
|
|
@@ -6445,14 +6373,14 @@ async function createServerHandle(config) {
|
|
|
6445
6373
|
const httpServer = createHttpServer(app);
|
|
6446
6374
|
const wssExports = createWebSocketServer(
|
|
6447
6375
|
httpServer,
|
|
6448
|
-
|
|
6376
|
+
config4,
|
|
6449
6377
|
getLLMClient,
|
|
6450
6378
|
() => providerManager.getActiveProvider(),
|
|
6451
6379
|
sessionManager,
|
|
6452
6380
|
providerManager
|
|
6453
6381
|
);
|
|
6454
6382
|
const wss = wssExports.wss;
|
|
6455
|
-
const { QueueProcessor } = await import("./processor-
|
|
6383
|
+
const { QueueProcessor } = await import("./processor-47OC5EUI.js");
|
|
6456
6384
|
const queueProcessor = new QueueProcessor({
|
|
6457
6385
|
sessionManager,
|
|
6458
6386
|
providerManager,
|
|
@@ -6471,17 +6399,17 @@ async function createServerHandle(config) {
|
|
|
6471
6399
|
};
|
|
6472
6400
|
return {
|
|
6473
6401
|
httpServer,
|
|
6474
|
-
ctx: { config, sessionManager, llmClient: getLLMClient(), toolRegistry, providerManager },
|
|
6402
|
+
ctx: { config: config4, sessionManager, llmClient: getLLMClient(), toolRegistry, providerManager },
|
|
6475
6403
|
start: (port) => new Promise((resolve2, reject) => {
|
|
6476
|
-
const listenPort = port ??
|
|
6477
|
-
const host =
|
|
6404
|
+
const listenPort = port ?? config4.server.port;
|
|
6405
|
+
const host = config4.server.host;
|
|
6478
6406
|
httpServer.listen(listenPort, host, () => {
|
|
6479
6407
|
const addr = httpServer.address();
|
|
6480
6408
|
const actualPort = typeof addr === "object" && addr ? addr.port : listenPort;
|
|
6481
6409
|
const client = getLLMClient();
|
|
6482
6410
|
logger.info(`OpenFox server running at http://${host}:${actualPort}`);
|
|
6483
6411
|
logger.info(`WebSocket available at ws://${host}:${actualPort}/ws`);
|
|
6484
|
-
logger.info(`LLM backend: ${client.getBackend()}, model: ${client.getModel()}, url: ${
|
|
6412
|
+
logger.info(`LLM backend: ${client.getBackend()}, model: ${client.getModel()}, url: ${config4.llm.baseUrl}`);
|
|
6485
6413
|
resolve2({ port: actualPort });
|
|
6486
6414
|
});
|
|
6487
6415
|
httpServer.on("error", reject);
|
|
@@ -6504,8 +6432,8 @@ async function createServerHandle(config) {
|
|
|
6504
6432
|
})
|
|
6505
6433
|
};
|
|
6506
6434
|
}
|
|
6507
|
-
async function createServer(
|
|
6508
|
-
const handle = await createServerHandle(
|
|
6435
|
+
async function createServer(config4) {
|
|
6436
|
+
const handle = await createServerHandle(config4);
|
|
6509
6437
|
await handle.start();
|
|
6510
6438
|
const shutdown = () => {
|
|
6511
6439
|
const forceExitTimer = setTimeout(() => {
|
|
@@ -6527,4 +6455,4 @@ export {
|
|
|
6527
6455
|
createServerHandle,
|
|
6528
6456
|
createServer
|
|
6529
6457
|
};
|
|
6530
|
-
//# sourceMappingURL=chunk-
|
|
6458
|
+
//# sourceMappingURL=chunk-UAV33LRW.js.map
|