openfox 1.6.14 → 1.6.16
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-C4PMBB24.js → auto-compaction-2RKC6DC2.js} +5 -5
- package/dist/{chat-handler-US3QOOE4.js → chat-handler-IY2XVOO6.js} +26 -56
- package/dist/{chunk-7HLRI6JM.js → chunk-2KP34IDL.js} +161 -204
- package/dist/{chunk-N25QUEPO.js → chunk-4OI4VPZ6.js} +434 -812
- package/dist/{chunk-XFXOSPYH.js → chunk-55N6FAAZ.js} +1 -1
- package/dist/{chunk-5GE3QJSZ.js → chunk-6L3X7T4K.js} +82 -160
- package/dist/{chunk-QDEKU5RL.js → chunk-F54ZJN4X.js} +38 -2
- package/dist/{chunk-UL4JYQKK.js → chunk-IN5EP4ZB.js} +2 -2
- package/dist/{chunk-OOIRCXAY.js → chunk-KOUMYBYM.js} +53 -112
- package/dist/{chunk-3JU6H6A4.js → chunk-NN65D5SI.js} +426 -448
- package/dist/{chunk-3XZ23PXM.js → chunk-OVLFEBRR.js} +76 -92
- package/dist/chunk-SN7OBEVL.js +44 -0
- package/dist/{chunk-PCOG5FQD.js → chunk-T5PBG2PE.js} +6 -6
- package/dist/{chunk-H22VHHQ4.js → chunk-U54QVKL2.js} +4 -4
- package/dist/{chunk-J2DHVXRX.js → chunk-ZDNXCVW4.js} +2 -2
- package/dist/cli/dev.js +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/{config-DEM6ASQM.js → config-67AX6CNS.js} +5 -5
- package/dist/{events-VDAC7E7K.js → events-2ETDOE5B.js} +3 -3
- package/dist/{folding-NDFQCISZ.js → folding-M7FMUBOL.js} +6 -4
- package/dist/{orchestrator-KZI7B5IS.js → orchestrator-U5VCLBYQ.js} +6 -6
- package/dist/package.json +13 -3
- package/dist/{processor-KBSF2HFD.js → processor-VUEJM73B.js} +24 -49
- package/dist/{provider-K3PHZO27.js → provider-DKGBQHUS.js} +7 -7
- package/dist/{serve-DERN4AB6.js → serve-GOLQMQFA.js} +12 -12
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.js +10 -10
- package/dist/{tools-PLVK22CF.js → tools-55YICCVH.js} +5 -5
- package/dist/{vision-fallback-NOC3YYIB.js → vision-fallback-ADYRFFD4.js} +2 -2
- package/dist/web/assets/index-CZBXRYpK.js +150 -0
- package/dist/web/assets/{index-MCWDS5UQ.css → index-D4V7Gtvt.css} +1 -1
- package/dist/web/index.html +2 -2
- package/dist/web/sw.js +1 -1
- package/package.json +13 -3
- package/dist/web/assets/index-Ccy2Csbl.js +0 -150
- /package/dist/{command-defaults → server/commands/defaults}/commit-push.command.md +0 -0
- /package/dist/{command-defaults → server/commands/defaults}/init.command.md +0 -0
- /package/dist/{command-defaults → server/commands/defaults}/test-ui.command.md +0 -0
- /package/dist/{skill-defaults → server/skills/defaults}/browser.skill.md +0 -0
|
@@ -1,50 +1,50 @@
|
|
|
1
1
|
import {
|
|
2
2
|
generateSessionName,
|
|
3
3
|
needsNameGeneration
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-F54ZJN4X.js";
|
|
5
5
|
import {
|
|
6
6
|
createVerifierNudgeConfig,
|
|
7
7
|
runBuilderTurn,
|
|
8
8
|
runChatTurn
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-U54QVKL2.js";
|
|
10
10
|
import {
|
|
11
11
|
TurnMetrics,
|
|
12
12
|
agentExists,
|
|
13
13
|
assembleAgentRequest,
|
|
14
14
|
cancelPathConfirmationsForSession,
|
|
15
|
+
checkAborted,
|
|
15
16
|
createChatDoneEvent,
|
|
16
17
|
createMessageStartEvent,
|
|
17
18
|
createToolRegistry,
|
|
18
19
|
deleteAgent,
|
|
19
20
|
deleteSkill,
|
|
20
21
|
devServerManager,
|
|
21
|
-
ensureDefaultAgents,
|
|
22
|
-
ensureDefaultSkills,
|
|
23
22
|
executeSubAgent,
|
|
24
23
|
findAgentById,
|
|
25
24
|
findSkillById,
|
|
26
25
|
getAllInstructions,
|
|
26
|
+
getDefaultAgentContent,
|
|
27
27
|
getDefaultAgentIds,
|
|
28
|
+
getDefaultSkillContent,
|
|
28
29
|
getDefaultSkillIds,
|
|
29
30
|
getEnabledSkillMetadata,
|
|
30
|
-
getModifiedDefaultAgentIds,
|
|
31
|
-
getModifiedDefaultSkillIds,
|
|
32
31
|
getToolRegistryForAgent,
|
|
33
32
|
isSkillEnabled,
|
|
34
33
|
loadAllAgents,
|
|
35
34
|
loadAllAgentsDefault,
|
|
36
35
|
loadAllSkills,
|
|
36
|
+
loadDefaultAgents,
|
|
37
|
+
loadDefaultSkills,
|
|
38
|
+
loadUserAgents,
|
|
39
|
+
loadUserSkills,
|
|
37
40
|
maybeAutoCompactContext,
|
|
38
41
|
performManualContextCompaction,
|
|
39
|
-
restoreAllDefaultAgents,
|
|
40
|
-
restoreAllDefaultSkills,
|
|
41
|
-
restoreDefaultAgent,
|
|
42
|
-
restoreDefaultSkill,
|
|
43
42
|
saveAgent,
|
|
44
43
|
saveSkill,
|
|
45
44
|
setSkillEnabled,
|
|
46
|
-
skillExists
|
|
47
|
-
|
|
45
|
+
skillExists,
|
|
46
|
+
spawnShellProcess
|
|
47
|
+
} from "./chunk-4OI4VPZ6.js";
|
|
48
48
|
import {
|
|
49
49
|
getPathSeparator,
|
|
50
50
|
getPlatformShell,
|
|
@@ -54,7 +54,7 @@ import {
|
|
|
54
54
|
import {
|
|
55
55
|
createProviderManager,
|
|
56
56
|
parseDefaultModelSelection
|
|
57
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-KOUMYBYM.js";
|
|
58
58
|
import {
|
|
59
59
|
SessionNotFoundError,
|
|
60
60
|
createLLMClient,
|
|
@@ -63,7 +63,7 @@ import {
|
|
|
63
63
|
getBackendDisplayName,
|
|
64
64
|
getLlmStatus,
|
|
65
65
|
getModelProfile
|
|
66
|
-
} from "./chunk-
|
|
66
|
+
} from "./chunk-OVLFEBRR.js";
|
|
67
67
|
import {
|
|
68
68
|
createSession,
|
|
69
69
|
deleteSession,
|
|
@@ -89,12 +89,12 @@ import {
|
|
|
89
89
|
updateSessionProvider,
|
|
90
90
|
updateSessionRunning,
|
|
91
91
|
updateSessionSummary
|
|
92
|
-
} from "./chunk-
|
|
92
|
+
} from "./chunk-6L3X7T4K.js";
|
|
93
93
|
import {
|
|
94
94
|
buildContextMessagesFromEventHistory,
|
|
95
95
|
buildMessagesFromStoredEvents,
|
|
96
96
|
foldPendingConfirmations
|
|
97
|
-
} from "./chunk-
|
|
97
|
+
} from "./chunk-2KP34IDL.js";
|
|
98
98
|
import {
|
|
99
99
|
createChatErrorMessage,
|
|
100
100
|
createChatMessageMessage,
|
|
@@ -145,7 +145,7 @@ import express from "express";
|
|
|
145
145
|
import cors from "cors";
|
|
146
146
|
import { createServer as createHttpServer } from "http";
|
|
147
147
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
148
|
-
import { dirname as dirname5, resolve, join as
|
|
148
|
+
import { dirname as dirname5, resolve, join as join6 } from "path";
|
|
149
149
|
import { readFile as readFile4 } from "fs/promises";
|
|
150
150
|
import { createServer as createViteServer } from "vite";
|
|
151
151
|
|
|
@@ -1414,7 +1414,7 @@ function unsubscribeAllFromTerminal(ws) {
|
|
|
1414
1414
|
}
|
|
1415
1415
|
|
|
1416
1416
|
// src/server/workflows/registry.ts
|
|
1417
|
-
import { readdir, readFile, writeFile,
|
|
1417
|
+
import { readdir, readFile, writeFile, mkdir, access, unlink } from "fs/promises";
|
|
1418
1418
|
import { join, dirname } from "path";
|
|
1419
1419
|
import { constants } from "fs";
|
|
1420
1420
|
import { fileURLToPath } from "url";
|
|
@@ -1433,49 +1433,20 @@ async function pathExists(path) {
|
|
|
1433
1433
|
return false;
|
|
1434
1434
|
}
|
|
1435
1435
|
}
|
|
1436
|
-
async function
|
|
1437
|
-
|
|
1438
|
-
if (!await pathExists(workflowsDir)) {
|
|
1439
|
-
await mkdir(workflowsDir, { recursive: true });
|
|
1440
|
-
}
|
|
1441
|
-
let defaultFiles;
|
|
1442
|
-
let sourceDir;
|
|
1443
|
-
try {
|
|
1444
|
-
defaultFiles = (await readdir(DEFAULTS_DIR)).filter((f) => f.endsWith(WORKFLOW_EXTENSION));
|
|
1445
|
-
sourceDir = DEFAULTS_DIR;
|
|
1446
|
-
} catch {
|
|
1447
|
-
try {
|
|
1448
|
-
defaultFiles = (await readdir(DEFAULTS_DIR_ALT)).filter((f) => f.endsWith(WORKFLOW_EXTENSION));
|
|
1449
|
-
sourceDir = DEFAULTS_DIR_ALT;
|
|
1450
|
-
} catch {
|
|
1451
|
-
logger.warn("No bundled workflow defaults found", { dir: DEFAULTS_DIR });
|
|
1452
|
-
return;
|
|
1453
|
-
}
|
|
1454
|
-
}
|
|
1455
|
-
for (const file of defaultFiles) {
|
|
1456
|
-
const targetPath = join(workflowsDir, file);
|
|
1457
|
-
try {
|
|
1458
|
-
await copyFile(join(sourceDir, file), targetPath);
|
|
1459
|
-
} catch (err) {
|
|
1460
|
-
logger.error("Failed to copy default workflow", { file, error: err instanceof Error ? err.message : String(err) });
|
|
1461
|
-
}
|
|
1462
|
-
}
|
|
1463
|
-
}
|
|
1464
|
-
async function loadAllWorkflows(configDir) {
|
|
1465
|
-
const workflowsDir = getWorkflowsDir(configDir);
|
|
1466
|
-
if (!await pathExists(workflowsDir)) {
|
|
1436
|
+
async function loadWorkflowsFromDir(dir) {
|
|
1437
|
+
if (!await pathExists(dir)) {
|
|
1467
1438
|
return [];
|
|
1468
1439
|
}
|
|
1469
1440
|
let files;
|
|
1470
1441
|
try {
|
|
1471
|
-
files = (await readdir(
|
|
1442
|
+
files = (await readdir(dir)).filter((f) => f.endsWith(WORKFLOW_EXTENSION));
|
|
1472
1443
|
} catch {
|
|
1473
1444
|
return [];
|
|
1474
1445
|
}
|
|
1475
1446
|
const workflows = [];
|
|
1476
1447
|
for (const file of files) {
|
|
1477
1448
|
try {
|
|
1478
|
-
const raw = await readFile(join(
|
|
1449
|
+
const raw = await readFile(join(dir, file), "utf-8");
|
|
1479
1450
|
const parsed = JSON.parse(raw);
|
|
1480
1451
|
if (parsed.metadata?.id && parsed.steps?.length > 0) {
|
|
1481
1452
|
workflows.push(parsed);
|
|
@@ -1488,6 +1459,30 @@ async function loadAllWorkflows(configDir) {
|
|
|
1488
1459
|
}
|
|
1489
1460
|
return workflows;
|
|
1490
1461
|
}
|
|
1462
|
+
async function loadDefaultWorkflows() {
|
|
1463
|
+
let defaults = await loadWorkflowsFromDir(DEFAULTS_DIR);
|
|
1464
|
+
if (!defaults.length) {
|
|
1465
|
+
defaults = await loadWorkflowsFromDir(DEFAULTS_DIR_ALT);
|
|
1466
|
+
}
|
|
1467
|
+
return defaults;
|
|
1468
|
+
}
|
|
1469
|
+
async function loadUserWorkflows(configDir) {
|
|
1470
|
+
return loadWorkflowsFromDir(getWorkflowsDir(configDir));
|
|
1471
|
+
}
|
|
1472
|
+
async function loadAllWorkflows(configDir) {
|
|
1473
|
+
const [defaultWorkflows, userWorkflows] = await Promise.all([
|
|
1474
|
+
loadDefaultWorkflows(),
|
|
1475
|
+
loadUserWorkflows(configDir)
|
|
1476
|
+
]);
|
|
1477
|
+
const workflowMap = /* @__PURE__ */ new Map();
|
|
1478
|
+
for (const workflow of defaultWorkflows) {
|
|
1479
|
+
workflowMap.set(workflow.metadata.id, workflow);
|
|
1480
|
+
}
|
|
1481
|
+
for (const workflow of userWorkflows) {
|
|
1482
|
+
workflowMap.set(workflow.metadata.id, workflow);
|
|
1483
|
+
}
|
|
1484
|
+
return Array.from(workflowMap.values());
|
|
1485
|
+
}
|
|
1491
1486
|
async function getDefaultWorkflowIds() {
|
|
1492
1487
|
for (const dir of [DEFAULTS_DIR, DEFAULTS_DIR_ALT]) {
|
|
1493
1488
|
try {
|
|
@@ -1498,50 +1493,13 @@ async function getDefaultWorkflowIds() {
|
|
|
1498
1493
|
}
|
|
1499
1494
|
return [];
|
|
1500
1495
|
}
|
|
1501
|
-
async function
|
|
1502
|
-
const
|
|
1503
|
-
|
|
1504
|
-
const sourcePath = join(dir, filename);
|
|
1505
|
-
if (await pathExists(sourcePath)) {
|
|
1506
|
-
const targetPath = join(getWorkflowsDir(configDir), filename);
|
|
1507
|
-
await copyFile(sourcePath, targetPath);
|
|
1508
|
-
return true;
|
|
1509
|
-
}
|
|
1510
|
-
}
|
|
1511
|
-
return false;
|
|
1496
|
+
async function getDefaultWorkflowContent(workflowId) {
|
|
1497
|
+
const defaults = await loadDefaultWorkflows();
|
|
1498
|
+
return defaults.find((w) => w.metadata.id === workflowId) ?? null;
|
|
1512
1499
|
}
|
|
1513
|
-
async function
|
|
1500
|
+
async function isDefaultWorkflow(workflowId) {
|
|
1514
1501
|
const defaultIds = await getDefaultWorkflowIds();
|
|
1515
|
-
|
|
1516
|
-
for (const id of defaultIds) {
|
|
1517
|
-
const filename = `${id}${WORKFLOW_EXTENSION}`;
|
|
1518
|
-
const userPath = join(getWorkflowsDir(configDir), filename);
|
|
1519
|
-
let bundledContent = null;
|
|
1520
|
-
for (const dir of [DEFAULTS_DIR, DEFAULTS_DIR_ALT]) {
|
|
1521
|
-
try {
|
|
1522
|
-
bundledContent = await readFile(join(dir, filename), "utf-8");
|
|
1523
|
-
break;
|
|
1524
|
-
} catch {
|
|
1525
|
-
}
|
|
1526
|
-
}
|
|
1527
|
-
if (!bundledContent) continue;
|
|
1528
|
-
try {
|
|
1529
|
-
const userContent = await readFile(userPath, "utf-8");
|
|
1530
|
-
if (userContent !== bundledContent) {
|
|
1531
|
-
modified.push(id);
|
|
1532
|
-
}
|
|
1533
|
-
} catch {
|
|
1534
|
-
}
|
|
1535
|
-
}
|
|
1536
|
-
return modified;
|
|
1537
|
-
}
|
|
1538
|
-
async function restoreAllDefaultWorkflows(configDir) {
|
|
1539
|
-
const ids = await getDefaultWorkflowIds();
|
|
1540
|
-
let count = 0;
|
|
1541
|
-
for (const id of ids) {
|
|
1542
|
-
if (await restoreDefaultWorkflow(configDir, id)) count++;
|
|
1543
|
-
}
|
|
1544
|
-
return count;
|
|
1502
|
+
return defaultIds.includes(workflowId);
|
|
1545
1503
|
}
|
|
1546
1504
|
function findWorkflowById(workflowId, workflows) {
|
|
1547
1505
|
return workflows.find((p) => p.metadata.id === workflowId);
|
|
@@ -1559,12 +1517,16 @@ async function saveWorkflow(configDir, workflow) {
|
|
|
1559
1517
|
await writeFile(filePath, JSON.stringify(workflow, null, 2) + "\n", "utf-8");
|
|
1560
1518
|
}
|
|
1561
1519
|
async function deleteWorkflow(configDir, workflowId) {
|
|
1520
|
+
const isDefault = await isDefaultWorkflow(workflowId);
|
|
1521
|
+
if (isDefault) {
|
|
1522
|
+
return { success: false, reason: "Cannot delete built-in defaults" };
|
|
1523
|
+
}
|
|
1562
1524
|
const filePath = join(getWorkflowsDir(configDir), `${workflowId}${WORKFLOW_EXTENSION}`);
|
|
1563
1525
|
try {
|
|
1564
1526
|
await unlink(filePath);
|
|
1565
|
-
return true;
|
|
1527
|
+
return { success: true };
|
|
1566
1528
|
} catch {
|
|
1567
|
-
return false;
|
|
1529
|
+
return { success: false };
|
|
1568
1530
|
}
|
|
1569
1531
|
}
|
|
1570
1532
|
|
|
@@ -1579,19 +1541,13 @@ var TERMINAL_DONE = "$done";
|
|
|
1579
1541
|
var TERMINAL_BLOCKED = "$blocked";
|
|
1580
1542
|
|
|
1581
1543
|
// src/server/workflows/shell.ts
|
|
1582
|
-
import { spawn as spawn2 } from "child_process";
|
|
1583
1544
|
function executeShellCommand(command, cwd, timeout, signal) {
|
|
1584
1545
|
return new Promise((resolve2, reject) => {
|
|
1585
|
-
if (signal
|
|
1546
|
+
if (checkAborted(signal)) {
|
|
1586
1547
|
reject(new Error("Aborted"));
|
|
1587
1548
|
return;
|
|
1588
1549
|
}
|
|
1589
|
-
const
|
|
1590
|
-
const proc = spawn2(shell.command, [...shell.args, command], {
|
|
1591
|
-
cwd,
|
|
1592
|
-
env: { ...process.env, FORCE_COLOR: "0" },
|
|
1593
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
1594
|
-
});
|
|
1550
|
+
const proc = spawnShellProcess(command, cwd, signal);
|
|
1595
1551
|
let stdout = "";
|
|
1596
1552
|
let stderr = "";
|
|
1597
1553
|
let killed = false;
|
|
@@ -1609,10 +1565,10 @@ function executeShellCommand(command, cwd, timeout, signal) {
|
|
|
1609
1565
|
}
|
|
1610
1566
|
};
|
|
1611
1567
|
signal?.addEventListener("abort", onAbort);
|
|
1612
|
-
proc.stdout
|
|
1568
|
+
proc.stdout?.on("data", (data) => {
|
|
1613
1569
|
stdout += data.toString();
|
|
1614
1570
|
});
|
|
1615
|
-
proc.stderr
|
|
1571
|
+
proc.stderr?.on("data", (data) => {
|
|
1616
1572
|
stderr += data.toString();
|
|
1617
1573
|
});
|
|
1618
1574
|
proc.on("close", (code) => {
|
|
@@ -1694,6 +1650,28 @@ function evaluateTransitions(transitions, criteria, stepOutcome) {
|
|
|
1694
1650
|
}
|
|
1695
1651
|
return TERMINAL_BLOCKED;
|
|
1696
1652
|
}
|
|
1653
|
+
function emitWorkflowMessage(eventStore, sessionId, content, windowOptions, onMessage) {
|
|
1654
|
+
const msgId = crypto.randomUUID();
|
|
1655
|
+
eventStore.append(sessionId, createMessageStartEvent(msgId, "user", content, {
|
|
1656
|
+
...windowOptions ?? {},
|
|
1657
|
+
isSystemGenerated: true,
|
|
1658
|
+
messageKind: "correction",
|
|
1659
|
+
metadata: { type: "workflow", name: "Workflow", color: "#f59e0b" }
|
|
1660
|
+
}));
|
|
1661
|
+
eventStore.append(sessionId, { type: "message.done", data: { messageId: msgId } });
|
|
1662
|
+
if (onMessage) {
|
|
1663
|
+
onMessage(createChatMessageMessage({
|
|
1664
|
+
id: msgId,
|
|
1665
|
+
role: "user",
|
|
1666
|
+
content,
|
|
1667
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1668
|
+
isSystemGenerated: true,
|
|
1669
|
+
messageKind: "correction",
|
|
1670
|
+
metadata: { type: "workflow", name: "Workflow", color: "#f59e0b" }
|
|
1671
|
+
}));
|
|
1672
|
+
}
|
|
1673
|
+
return msgId;
|
|
1674
|
+
}
|
|
1697
1675
|
function getCurrentWindowMessageOptions(sessionId) {
|
|
1698
1676
|
const contextWindowId = getCurrentContextWindowId(sessionId);
|
|
1699
1677
|
return contextWindowId ? { contextWindowId } : void 0;
|
|
@@ -1823,25 +1801,7 @@ async function executeWorkflow(workflow, options) {
|
|
|
1823
1801
|
}
|
|
1824
1802
|
parts.push(STEP_DONE_NUDGE);
|
|
1825
1803
|
nudgeContent = parts.join("\n\n");
|
|
1826
|
-
|
|
1827
|
-
eventStore.append(sessionId, createMessageStartEvent(nudgeMsgId, "user", nudgeContent, {
|
|
1828
|
-
...currentWindowMessageOptions ?? {},
|
|
1829
|
-
isSystemGenerated: true,
|
|
1830
|
-
messageKind: "correction",
|
|
1831
|
-
metadata: { type: "workflow", name: "Workflow", color: "#f59e0b" }
|
|
1832
|
-
}));
|
|
1833
|
-
eventStore.append(sessionId, { type: "message.done", data: { messageId: nudgeMsgId } });
|
|
1834
|
-
if (onMessage) {
|
|
1835
|
-
onMessage(createChatMessageMessage({
|
|
1836
|
-
id: nudgeMsgId,
|
|
1837
|
-
role: "user",
|
|
1838
|
-
content: nudgeContent,
|
|
1839
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1840
|
-
isSystemGenerated: true,
|
|
1841
|
-
messageKind: "correction",
|
|
1842
|
-
metadata: { type: "workflow", name: "Workflow", color: "#f59e0b" }
|
|
1843
|
-
}));
|
|
1844
|
-
}
|
|
1804
|
+
emitWorkflowMessage(eventStore, sessionId, nudgeContent, currentWindowMessageOptions, onMessage);
|
|
1845
1805
|
}
|
|
1846
1806
|
const turnMetrics = new TurnMetrics();
|
|
1847
1807
|
const agentResult = await runBuilderTurn({
|
|
@@ -2003,25 +1963,7 @@ ${output.slice(0, 1e4)}
|
|
|
2003
1963
|
sessionManager.setPhase(sessionId, "blocked");
|
|
2004
1964
|
const blockedCriteria = refreshedSession.criteria.filter((c) => c.status.type === "failed" && c.attempts.filter((a) => a.status === "failed").length >= RUNNER_CONFIG.maxVerifyRetries).map((c) => c.id);
|
|
2005
1965
|
const reason = blockedCriteria.length > 0 ? `Retry limit reached for: ${blockedCriteria.join(", ")}` : "No matching transition";
|
|
2006
|
-
|
|
2007
|
-
eventStore.append(sessionId, createMessageStartEvent(blockedMsgId, "user", `Runner blocked: ${reason}`, {
|
|
2008
|
-
...currentWindowMessageOptions ?? {},
|
|
2009
|
-
isSystemGenerated: true,
|
|
2010
|
-
messageKind: "correction",
|
|
2011
|
-
metadata: { type: "workflow", name: "Workflow", color: "#f59e0b" }
|
|
2012
|
-
}));
|
|
2013
|
-
eventStore.append(sessionId, { type: "message.done", data: { messageId: blockedMsgId } });
|
|
2014
|
-
if (onMessage) {
|
|
2015
|
-
onMessage(createChatMessageMessage({
|
|
2016
|
-
id: blockedMsgId,
|
|
2017
|
-
role: "user",
|
|
2018
|
-
content: `Runner blocked: ${reason}`,
|
|
2019
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2020
|
-
isSystemGenerated: true,
|
|
2021
|
-
messageKind: "correction",
|
|
2022
|
-
metadata: { type: "workflow", name: "Workflow", color: "#f59e0b" }
|
|
2023
|
-
}));
|
|
2024
|
-
}
|
|
1966
|
+
emitWorkflowMessage(eventStore, sessionId, `Runner blocked: ${reason}`, currentWindowMessageOptions, onMessage);
|
|
2025
1967
|
logger.warn("Workflow executor blocked", { sessionId, iterations, reason });
|
|
2026
1968
|
const blockedAction = { type: "BLOCKED", reason, blockedCriteria };
|
|
2027
1969
|
return {
|
|
@@ -3174,7 +3116,7 @@ ${content}` : workflowInfo;
|
|
|
3174
3116
|
}
|
|
3175
3117
|
|
|
3176
3118
|
// src/server/lsp/server.ts
|
|
3177
|
-
import { spawn as
|
|
3119
|
+
import { spawn as spawn2 } from "child_process";
|
|
3178
3120
|
import { extname } from "path";
|
|
3179
3121
|
import { createMessageConnection, StreamMessageReader, StreamMessageWriter } from "vscode-jsonrpc/node.js";
|
|
3180
3122
|
var LSP = {
|
|
@@ -3236,7 +3178,7 @@ var LspServer = class {
|
|
|
3236
3178
|
}
|
|
3237
3179
|
this.state = "starting";
|
|
3238
3180
|
try {
|
|
3239
|
-
this.process =
|
|
3181
|
+
this.process = spawn2(this.commandPath, this.config.serverArgs, {
|
|
3240
3182
|
cwd: this.workdir,
|
|
3241
3183
|
stdio: ["pipe", "pipe", "pipe"],
|
|
3242
3184
|
env: {
|
|
@@ -4923,202 +4865,47 @@ ${summary}`,
|
|
|
4923
4865
|
}
|
|
4924
4866
|
};
|
|
4925
4867
|
|
|
4926
|
-
// src/server/
|
|
4927
|
-
import {
|
|
4928
|
-
|
|
4929
|
-
|
|
4930
|
-
|
|
4931
|
-
|
|
4932
|
-
var __bundleDir2 = dirname4(fileURLToPath3(import.meta.url));
|
|
4933
|
-
var DEFAULTS_DIR2 = join4(__bundleDir2, "defaults");
|
|
4934
|
-
var DEFAULTS_DIR_ALT2 = join4(__bundleDir2, "command-defaults");
|
|
4935
|
-
var COMMAND_EXTENSION = ".command.md";
|
|
4936
|
-
function getCommandsDir(configDir) {
|
|
4937
|
-
return join4(configDir, "commands");
|
|
4938
|
-
}
|
|
4939
|
-
async function dirExists(path) {
|
|
4940
|
-
try {
|
|
4941
|
-
await access3(path, constants3.R_OK);
|
|
4942
|
-
return true;
|
|
4943
|
-
} catch {
|
|
4944
|
-
return false;
|
|
4945
|
-
}
|
|
4946
|
-
}
|
|
4947
|
-
async function ensureDefaultCommands(configDir) {
|
|
4948
|
-
const commandsDir = getCommandsDir(configDir);
|
|
4949
|
-
if (!await dirExists(commandsDir)) {
|
|
4950
|
-
await mkdir3(commandsDir, { recursive: true });
|
|
4951
|
-
}
|
|
4952
|
-
let defaultFiles;
|
|
4953
|
-
let sourceDir;
|
|
4954
|
-
try {
|
|
4955
|
-
defaultFiles = (await readdir2(DEFAULTS_DIR2)).filter((f) => f.endsWith(COMMAND_EXTENSION));
|
|
4956
|
-
sourceDir = DEFAULTS_DIR2;
|
|
4957
|
-
} catch {
|
|
4958
|
-
try {
|
|
4959
|
-
defaultFiles = (await readdir2(DEFAULTS_DIR_ALT2)).filter((f) => f.endsWith(COMMAND_EXTENSION));
|
|
4960
|
-
sourceDir = DEFAULTS_DIR_ALT2;
|
|
4961
|
-
} catch {
|
|
4962
|
-
logger.warn("No bundled command defaults found", { dir: DEFAULTS_DIR2 });
|
|
4963
|
-
return;
|
|
4964
|
-
}
|
|
4965
|
-
}
|
|
4966
|
-
for (const file of defaultFiles) {
|
|
4967
|
-
const targetPath = join4(commandsDir, file);
|
|
4968
|
-
if (!await dirExists(targetPath)) {
|
|
4969
|
-
try {
|
|
4970
|
-
await copyFile2(join4(sourceDir, file), targetPath);
|
|
4971
|
-
logger.info("Installed default command", { file });
|
|
4972
|
-
} catch (err) {
|
|
4973
|
-
logger.error("Failed to copy default command", { file, error: err instanceof Error ? err.message : String(err) });
|
|
4974
|
-
}
|
|
4975
|
-
}
|
|
4976
|
-
}
|
|
4977
|
-
}
|
|
4978
|
-
async function loadAllCommands(configDir) {
|
|
4979
|
-
const commandsDir = getCommandsDir(configDir);
|
|
4980
|
-
if (!await dirExists(commandsDir)) {
|
|
4981
|
-
return [];
|
|
4982
|
-
}
|
|
4983
|
-
let files;
|
|
4984
|
-
try {
|
|
4985
|
-
files = (await readdir2(commandsDir)).filter((f) => f.endsWith(COMMAND_EXTENSION));
|
|
4986
|
-
} catch {
|
|
4987
|
-
return [];
|
|
4988
|
-
}
|
|
4989
|
-
const commands = [];
|
|
4990
|
-
for (const file of files) {
|
|
4991
|
-
try {
|
|
4992
|
-
const raw = await readFile3(join4(commandsDir, file), "utf-8");
|
|
4993
|
-
const { data, content } = matter(raw);
|
|
4994
|
-
const metadata = data;
|
|
4995
|
-
if (metadata.id && content.trim()) {
|
|
4996
|
-
commands.push({ metadata, prompt: content.trim() });
|
|
4997
|
-
} else {
|
|
4998
|
-
logger.warn("Skipping invalid command file", { file });
|
|
4999
|
-
}
|
|
5000
|
-
} catch (err) {
|
|
5001
|
-
logger.warn("Failed to parse command file", { file, error: err instanceof Error ? err.message : String(err) });
|
|
5002
|
-
}
|
|
5003
|
-
}
|
|
5004
|
-
return commands;
|
|
5005
|
-
}
|
|
5006
|
-
async function getDefaultCommandIds() {
|
|
5007
|
-
for (const dir of [DEFAULTS_DIR2, DEFAULTS_DIR_ALT2]) {
|
|
5008
|
-
try {
|
|
5009
|
-
const files = (await readdir2(dir)).filter((f) => f.endsWith(COMMAND_EXTENSION));
|
|
5010
|
-
return files.map((f) => f.replace(COMMAND_EXTENSION, ""));
|
|
5011
|
-
} catch {
|
|
5012
|
-
}
|
|
5013
|
-
}
|
|
5014
|
-
return [];
|
|
5015
|
-
}
|
|
5016
|
-
async function restoreDefaultCommand(configDir, commandId) {
|
|
5017
|
-
const filename = `${commandId}${COMMAND_EXTENSION}`;
|
|
5018
|
-
for (const dir of [DEFAULTS_DIR2, DEFAULTS_DIR_ALT2]) {
|
|
5019
|
-
const sourcePath = join4(dir, filename);
|
|
5020
|
-
if (await dirExists(sourcePath)) {
|
|
5021
|
-
const targetPath = join4(getCommandsDir(configDir), filename);
|
|
5022
|
-
await copyFile2(sourcePath, targetPath);
|
|
5023
|
-
return true;
|
|
5024
|
-
}
|
|
5025
|
-
}
|
|
5026
|
-
return false;
|
|
5027
|
-
}
|
|
5028
|
-
async function getModifiedDefaultCommandIds(configDir) {
|
|
5029
|
-
const defaultIds = await getDefaultCommandIds();
|
|
5030
|
-
const modified = [];
|
|
5031
|
-
for (const id of defaultIds) {
|
|
5032
|
-
const filename = `${id}${COMMAND_EXTENSION}`;
|
|
5033
|
-
const userPath = join4(getCommandsDir(configDir), filename);
|
|
5034
|
-
let bundledContent = null;
|
|
5035
|
-
for (const dir of [DEFAULTS_DIR2, DEFAULTS_DIR_ALT2]) {
|
|
5036
|
-
try {
|
|
5037
|
-
bundledContent = await readFile3(join4(dir, filename), "utf-8");
|
|
5038
|
-
break;
|
|
5039
|
-
} catch {
|
|
5040
|
-
}
|
|
5041
|
-
}
|
|
5042
|
-
if (!bundledContent) continue;
|
|
5043
|
-
try {
|
|
5044
|
-
const userContent = await readFile3(userPath, "utf-8");
|
|
5045
|
-
if (userContent !== bundledContent) {
|
|
5046
|
-
modified.push(id);
|
|
5047
|
-
}
|
|
5048
|
-
} catch {
|
|
5049
|
-
}
|
|
5050
|
-
}
|
|
5051
|
-
return modified;
|
|
5052
|
-
}
|
|
5053
|
-
async function restoreAllDefaultCommands(configDir) {
|
|
5054
|
-
const ids = await getDefaultCommandIds();
|
|
5055
|
-
let count = 0;
|
|
5056
|
-
for (const id of ids) {
|
|
5057
|
-
if (await restoreDefaultCommand(configDir, id)) count++;
|
|
5058
|
-
}
|
|
5059
|
-
return count;
|
|
5060
|
-
}
|
|
5061
|
-
function findCommandById(commandId, commands) {
|
|
5062
|
-
return commands.find((c) => c.metadata.id === commandId);
|
|
5063
|
-
}
|
|
5064
|
-
async function commandExists(configDir, commandId) {
|
|
5065
|
-
const filePath = join4(getCommandsDir(configDir), `${commandId}${COMMAND_EXTENSION}`);
|
|
5066
|
-
return dirExists(filePath);
|
|
5067
|
-
}
|
|
5068
|
-
async function saveCommand(configDir, command) {
|
|
5069
|
-
const commandsDir = getCommandsDir(configDir);
|
|
5070
|
-
if (!await dirExists(commandsDir)) {
|
|
5071
|
-
await mkdir3(commandsDir, { recursive: true });
|
|
5072
|
-
}
|
|
5073
|
-
const filePath = join4(commandsDir, `${command.metadata.id}${COMMAND_EXTENSION}`);
|
|
5074
|
-
const content = matter.stringify(command.prompt, command.metadata);
|
|
5075
|
-
await writeFile3(filePath, content, "utf-8");
|
|
5076
|
-
}
|
|
5077
|
-
async function deleteCommand(configDir, commandId) {
|
|
5078
|
-
const filePath = join4(getCommandsDir(configDir), `${commandId}${COMMAND_EXTENSION}`);
|
|
5079
|
-
try {
|
|
5080
|
-
await unlink2(filePath);
|
|
5081
|
-
return true;
|
|
5082
|
-
} catch {
|
|
5083
|
-
return false;
|
|
5084
|
-
}
|
|
4868
|
+
// src/server/routes/skills.ts
|
|
4869
|
+
import { Router } from "express";
|
|
4870
|
+
|
|
4871
|
+
// src/server/routes/crud-helpers.ts
|
|
4872
|
+
function computeOverrideIds(defaults, userItems) {
|
|
4873
|
+
return userItems.filter((u) => defaults.some((d) => d.metadata.id === u.metadata.id)).map((u) => u.metadata.id);
|
|
5085
4874
|
}
|
|
5086
4875
|
|
|
5087
4876
|
// src/server/routes/skills.ts
|
|
5088
|
-
import { Router } from "express";
|
|
5089
4877
|
function createSkillRoutes(configDir) {
|
|
5090
4878
|
const router = Router();
|
|
5091
4879
|
router.get("/", async (_req, res) => {
|
|
5092
|
-
const [
|
|
5093
|
-
|
|
5094
|
-
|
|
5095
|
-
getModifiedDefaultSkillIds(configDir)
|
|
4880
|
+
const [defaults, userItems] = await Promise.all([
|
|
4881
|
+
loadDefaultSkills(),
|
|
4882
|
+
loadUserSkills(configDir)
|
|
5096
4883
|
]);
|
|
4884
|
+
const overrideIds = computeOverrideIds(defaults, userItems);
|
|
5097
4885
|
res.json({
|
|
5098
|
-
|
|
4886
|
+
defaults: defaults.map((s) => ({
|
|
5099
4887
|
...s.metadata,
|
|
5100
4888
|
enabled: isSkillEnabled(s.metadata.id)
|
|
5101
4889
|
})),
|
|
5102
|
-
|
|
5103
|
-
|
|
4890
|
+
userItems: userItems.map((s) => ({
|
|
4891
|
+
...s.metadata,
|
|
4892
|
+
enabled: isSkillEnabled(s.metadata.id)
|
|
4893
|
+
})),
|
|
4894
|
+
overrideIds
|
|
5104
4895
|
});
|
|
5105
4896
|
});
|
|
4897
|
+
router.get("/defaults/:id", async (req, res) => {
|
|
4898
|
+
const { id } = req.params;
|
|
4899
|
+
const content = await getDefaultSkillContent(id);
|
|
4900
|
+
if (!content) {
|
|
4901
|
+
return res.status(404).json({ error: "Default skill not found" });
|
|
4902
|
+
}
|
|
4903
|
+
res.json(content);
|
|
4904
|
+
});
|
|
5106
4905
|
router.get("/default-ids", async (_req, res) => {
|
|
5107
4906
|
const ids = await getDefaultSkillIds();
|
|
5108
4907
|
res.json({ ids });
|
|
5109
4908
|
});
|
|
5110
|
-
router.post("/restore-all-defaults", async (_req, res) => {
|
|
5111
|
-
const count = await restoreAllDefaultSkills(configDir);
|
|
5112
|
-
res.json({ success: true, count });
|
|
5113
|
-
});
|
|
5114
|
-
router.post("/:id/restore-default", async (req, res) => {
|
|
5115
|
-
const { id } = req.params;
|
|
5116
|
-
const restored = await restoreDefaultSkill(configDir, id);
|
|
5117
|
-
if (!restored) {
|
|
5118
|
-
return res.status(404).json({ error: "No bundled default found for this skill" });
|
|
5119
|
-
}
|
|
5120
|
-
res.json({ success: true });
|
|
5121
|
-
});
|
|
5122
4909
|
router.post("/:id/toggle", (req, res) => {
|
|
5123
4910
|
const { id } = req.params;
|
|
5124
4911
|
const currentlyEnabled = isSkillEnabled(id);
|
|
@@ -5142,7 +4929,8 @@ function createSkillRoutes(configDir) {
|
|
|
5142
4929
|
if (!/^[a-z0-9-]+$/.test(body.metadata.id)) {
|
|
5143
4930
|
return res.status(400).json({ error: "Skill ID must be lowercase alphanumeric with hyphens only" });
|
|
5144
4931
|
}
|
|
5145
|
-
|
|
4932
|
+
const exists = await skillExists(configDir, body.metadata.id);
|
|
4933
|
+
if (exists) {
|
|
5146
4934
|
return res.status(409).json({ error: "A skill with this ID already exists" });
|
|
5147
4935
|
}
|
|
5148
4936
|
await saveSkill(configDir, body);
|
|
@@ -5150,15 +4938,12 @@ function createSkillRoutes(configDir) {
|
|
|
5150
4938
|
});
|
|
5151
4939
|
router.put("/:id", async (req, res) => {
|
|
5152
4940
|
const { id } = req.params;
|
|
5153
|
-
if (!await skillExists(configDir, id)) {
|
|
5154
|
-
return res.status(404).json({ error: "Skill not found" });
|
|
5155
|
-
}
|
|
5156
|
-
const body = req.body;
|
|
5157
4941
|
const skills = await loadAllSkills(configDir);
|
|
5158
4942
|
const existing = findSkillById(id, skills);
|
|
5159
4943
|
if (!existing) {
|
|
5160
4944
|
return res.status(404).json({ error: "Skill not found" });
|
|
5161
4945
|
}
|
|
4946
|
+
const body = req.body;
|
|
5162
4947
|
const updated = {
|
|
5163
4948
|
metadata: { ...existing.metadata, ...body.metadata, id },
|
|
5164
4949
|
prompt: body.prompt ?? existing.prompt
|
|
@@ -5168,47 +4953,205 @@ function createSkillRoutes(configDir) {
|
|
|
5168
4953
|
});
|
|
5169
4954
|
router.delete("/:id", async (req, res) => {
|
|
5170
4955
|
const { id } = req.params;
|
|
5171
|
-
const
|
|
5172
|
-
if (!
|
|
5173
|
-
return res.status(
|
|
4956
|
+
const result = await deleteSkill(configDir, id);
|
|
4957
|
+
if (!result.success) {
|
|
4958
|
+
return res.status(403).json({ error: result.reason ?? "Cannot delete this skill" });
|
|
5174
4959
|
}
|
|
5175
4960
|
res.json({ success: true });
|
|
5176
4961
|
});
|
|
4962
|
+
router.post("/:id/duplicate", async (req, res) => {
|
|
4963
|
+
const { id } = req.params;
|
|
4964
|
+
const defaults = await loadDefaultSkills();
|
|
4965
|
+
const userItems = await loadUserSkills(configDir);
|
|
4966
|
+
const source = defaults.find((s) => s.metadata.id === id) ?? userItems.find((s) => s.metadata.id === id);
|
|
4967
|
+
if (!source) {
|
|
4968
|
+
return res.status(404).json({ error: "Skill not found" });
|
|
4969
|
+
}
|
|
4970
|
+
const newId = `${id}-copy-${Date.now()}`;
|
|
4971
|
+
const duplicated = {
|
|
4972
|
+
metadata: { ...source.metadata, id: newId, name: `${source.metadata.name} (copy)` },
|
|
4973
|
+
prompt: source.prompt
|
|
4974
|
+
};
|
|
4975
|
+
await saveSkill(configDir, duplicated);
|
|
4976
|
+
res.status(201).json(duplicated);
|
|
4977
|
+
});
|
|
5177
4978
|
return router;
|
|
5178
4979
|
}
|
|
5179
4980
|
|
|
5180
4981
|
// src/server/routes/commands.ts
|
|
5181
4982
|
import { Router as Router2 } from "express";
|
|
4983
|
+
|
|
4984
|
+
// src/server/commands/registry.ts
|
|
4985
|
+
import { join as join5 } from "path";
|
|
4986
|
+
|
|
4987
|
+
// src/server/commands/registry-utils.ts
|
|
4988
|
+
import { readdir as readdir2, readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3, access as access3, unlink as unlink2 } from "fs/promises";
|
|
4989
|
+
import { join as join4, dirname as dirname4 } from "path";
|
|
4990
|
+
import { constants as constants3 } from "fs";
|
|
4991
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
4992
|
+
import matter from "gray-matter";
|
|
4993
|
+
function getBundleDir() {
|
|
4994
|
+
return dirname4(fileURLToPath3(import.meta.url));
|
|
4995
|
+
}
|
|
4996
|
+
async function dirExists(path) {
|
|
4997
|
+
try {
|
|
4998
|
+
await access3(path, constants3.R_OK);
|
|
4999
|
+
return true;
|
|
5000
|
+
} catch {
|
|
5001
|
+
return false;
|
|
5002
|
+
}
|
|
5003
|
+
}
|
|
5004
|
+
async function ensureDir(path) {
|
|
5005
|
+
if (!await dirExists(path)) {
|
|
5006
|
+
await mkdir3(path, { recursive: true });
|
|
5007
|
+
}
|
|
5008
|
+
}
|
|
5009
|
+
async function loadItems(dir, extension) {
|
|
5010
|
+
if (!await dirExists(dir)) return [];
|
|
5011
|
+
let files;
|
|
5012
|
+
try {
|
|
5013
|
+
files = (await readdir2(dir)).filter((f) => f.endsWith(extension));
|
|
5014
|
+
} catch {
|
|
5015
|
+
return [];
|
|
5016
|
+
}
|
|
5017
|
+
const items = [];
|
|
5018
|
+
for (const file of files) {
|
|
5019
|
+
try {
|
|
5020
|
+
const raw = await readFile3(join4(dir, file), "utf-8");
|
|
5021
|
+
const { data, content } = matter(raw);
|
|
5022
|
+
if (data.id && content.trim()) {
|
|
5023
|
+
items.push({ metadata: data, prompt: content.trim() });
|
|
5024
|
+
} else {
|
|
5025
|
+
logger.warn(`Skipping invalid ${extension} file`, { file });
|
|
5026
|
+
}
|
|
5027
|
+
} catch (err) {
|
|
5028
|
+
logger.warn(`Failed to parse ${extension} file`, { file, error: err instanceof Error ? err.message : String(err) });
|
|
5029
|
+
}
|
|
5030
|
+
}
|
|
5031
|
+
return items;
|
|
5032
|
+
}
|
|
5033
|
+
async function saveItem(dir, id, extension, item) {
|
|
5034
|
+
await ensureDir(dir);
|
|
5035
|
+
const filePath = join4(dir, `${id}${extension}`);
|
|
5036
|
+
const content = matter.stringify(item.prompt, item.metadata);
|
|
5037
|
+
await writeFile3(filePath, content, "utf-8");
|
|
5038
|
+
}
|
|
5039
|
+
async function deleteItem(dir, id, extension) {
|
|
5040
|
+
const filePath = join4(dir, `${id}${extension}`);
|
|
5041
|
+
try {
|
|
5042
|
+
await unlink2(filePath);
|
|
5043
|
+
return true;
|
|
5044
|
+
} catch {
|
|
5045
|
+
return false;
|
|
5046
|
+
}
|
|
5047
|
+
}
|
|
5048
|
+
function findById(id, items) {
|
|
5049
|
+
return items.find((i) => i.metadata.id === id);
|
|
5050
|
+
}
|
|
5051
|
+
async function getDefaultIds(bundleDir, defaultsDir, extension) {
|
|
5052
|
+
try {
|
|
5053
|
+
const files = (await readdir2(join4(bundleDir, defaultsDir))).filter((f) => f.endsWith(extension));
|
|
5054
|
+
return files.map((f) => f.replace(extension, ""));
|
|
5055
|
+
} catch {
|
|
5056
|
+
return [];
|
|
5057
|
+
}
|
|
5058
|
+
}
|
|
5059
|
+
async function loadDefaults(bundleDir, defaultsDir, extension) {
|
|
5060
|
+
const dir = join4(bundleDir, defaultsDir);
|
|
5061
|
+
return loadItems(dir, extension);
|
|
5062
|
+
}
|
|
5063
|
+
|
|
5064
|
+
// src/server/commands/registry.ts
|
|
5065
|
+
var DEFAULTS_DIR2 = "defaults";
|
|
5066
|
+
var DEFAULTS_DIR_ALT2 = "command-defaults";
|
|
5067
|
+
var COMMAND_EXTENSION = ".command.md";
|
|
5068
|
+
function getCommandsDir(configDir) {
|
|
5069
|
+
return join5(configDir, "commands");
|
|
5070
|
+
}
|
|
5071
|
+
async function loadDefaultCommands() {
|
|
5072
|
+
const bundleDir = getBundleDir();
|
|
5073
|
+
let defaults = await loadDefaults(bundleDir, DEFAULTS_DIR2, COMMAND_EXTENSION);
|
|
5074
|
+
if (!defaults.length) {
|
|
5075
|
+
defaults = await loadDefaults(bundleDir, DEFAULTS_DIR_ALT2, COMMAND_EXTENSION);
|
|
5076
|
+
}
|
|
5077
|
+
return defaults;
|
|
5078
|
+
}
|
|
5079
|
+
async function loadUserCommands(configDir) {
|
|
5080
|
+
return loadItems(getCommandsDir(configDir), COMMAND_EXTENSION);
|
|
5081
|
+
}
|
|
5082
|
+
async function loadAllCommands(configDir) {
|
|
5083
|
+
const [defaultCommands, userCommands] = await Promise.all([
|
|
5084
|
+
loadDefaultCommands(),
|
|
5085
|
+
loadUserCommands(configDir)
|
|
5086
|
+
]);
|
|
5087
|
+
const commandMap = /* @__PURE__ */ new Map();
|
|
5088
|
+
for (const cmd of defaultCommands) {
|
|
5089
|
+
commandMap.set(cmd.metadata.id, cmd);
|
|
5090
|
+
}
|
|
5091
|
+
for (const cmd of userCommands) {
|
|
5092
|
+
commandMap.set(cmd.metadata.id, cmd);
|
|
5093
|
+
}
|
|
5094
|
+
return Array.from(commandMap.values());
|
|
5095
|
+
}
|
|
5096
|
+
async function getDefaultCommandIds() {
|
|
5097
|
+
const bundleDir = getBundleDir();
|
|
5098
|
+
const ids = await getDefaultIds(bundleDir, DEFAULTS_DIR2, COMMAND_EXTENSION);
|
|
5099
|
+
if (ids.length) return ids;
|
|
5100
|
+
return getDefaultIds(bundleDir, DEFAULTS_DIR_ALT2, COMMAND_EXTENSION);
|
|
5101
|
+
}
|
|
5102
|
+
async function getDefaultCommandContent(commandId) {
|
|
5103
|
+
const defaults = await loadDefaultCommands();
|
|
5104
|
+
return defaults.find((c) => c.metadata.id === commandId) ?? null;
|
|
5105
|
+
}
|
|
5106
|
+
async function isDefaultCommand(commandId) {
|
|
5107
|
+
const defaultIds = await getDefaultCommandIds();
|
|
5108
|
+
return defaultIds.includes(commandId);
|
|
5109
|
+
}
|
|
5110
|
+
function findCommandById(commandId, commands) {
|
|
5111
|
+
return findById(commandId, commands);
|
|
5112
|
+
}
|
|
5113
|
+
async function commandExists(configDir, commandId) {
|
|
5114
|
+
return dirExists(join5(getCommandsDir(configDir), `${commandId}${COMMAND_EXTENSION}`));
|
|
5115
|
+
}
|
|
5116
|
+
async function saveCommand(configDir, command) {
|
|
5117
|
+
return saveItem(getCommandsDir(configDir), command.metadata.id, COMMAND_EXTENSION, command);
|
|
5118
|
+
}
|
|
5119
|
+
async function deleteCommand(configDir, commandId) {
|
|
5120
|
+
const isDefault = await isDefaultCommand(commandId);
|
|
5121
|
+
if (isDefault) {
|
|
5122
|
+
return { success: false, reason: "Cannot delete built-in defaults" };
|
|
5123
|
+
}
|
|
5124
|
+
const deleted = await deleteItem(getCommandsDir(configDir), commandId, COMMAND_EXTENSION);
|
|
5125
|
+
return { success: deleted };
|
|
5126
|
+
}
|
|
5127
|
+
|
|
5128
|
+
// src/server/routes/commands.ts
|
|
5182
5129
|
function createCommandRoutes(configDir) {
|
|
5183
5130
|
const router = Router2();
|
|
5184
5131
|
router.get("/", async (_req, res) => {
|
|
5185
|
-
const [
|
|
5186
|
-
|
|
5187
|
-
|
|
5188
|
-
getModifiedDefaultCommandIds(configDir)
|
|
5132
|
+
const [defaults, userItems] = await Promise.all([
|
|
5133
|
+
loadDefaultCommands(),
|
|
5134
|
+
loadUserCommands(configDir)
|
|
5189
5135
|
]);
|
|
5136
|
+
const overrideIds = computeOverrideIds(defaults, userItems);
|
|
5190
5137
|
res.json({
|
|
5191
|
-
|
|
5192
|
-
|
|
5193
|
-
|
|
5138
|
+
defaults: defaults.map((c) => c.metadata),
|
|
5139
|
+
userItems: userItems.map((c) => c.metadata),
|
|
5140
|
+
overrideIds
|
|
5194
5141
|
});
|
|
5195
5142
|
});
|
|
5143
|
+
router.get("/defaults/:id", async (req, res) => {
|
|
5144
|
+
const { id } = req.params;
|
|
5145
|
+
const content = await getDefaultCommandContent(id);
|
|
5146
|
+
if (!content) {
|
|
5147
|
+
return res.status(404).json({ error: "Default command not found" });
|
|
5148
|
+
}
|
|
5149
|
+
res.json(content);
|
|
5150
|
+
});
|
|
5196
5151
|
router.get("/default-ids", async (_req, res) => {
|
|
5197
5152
|
const ids = await getDefaultCommandIds();
|
|
5198
5153
|
res.json({ ids });
|
|
5199
5154
|
});
|
|
5200
|
-
router.post("/restore-all-defaults", async (_req, res) => {
|
|
5201
|
-
const count = await restoreAllDefaultCommands(configDir);
|
|
5202
|
-
res.json({ success: true, count });
|
|
5203
|
-
});
|
|
5204
|
-
router.post("/:id/restore-default", async (req, res) => {
|
|
5205
|
-
const { id } = req.params;
|
|
5206
|
-
const restored = await restoreDefaultCommand(configDir, id);
|
|
5207
|
-
if (!restored) {
|
|
5208
|
-
return res.status(404).json({ error: "No bundled default found for this command" });
|
|
5209
|
-
}
|
|
5210
|
-
res.json({ success: true });
|
|
5211
|
-
});
|
|
5212
5155
|
router.get("/:id", async (req, res) => {
|
|
5213
5156
|
const { id } = req.params;
|
|
5214
5157
|
const commands = await loadAllCommands(configDir);
|
|
@@ -5226,7 +5169,8 @@ function createCommandRoutes(configDir) {
|
|
|
5226
5169
|
if (!/^[a-z0-9-]+$/.test(body.metadata.id)) {
|
|
5227
5170
|
return res.status(400).json({ error: "Command ID must be lowercase alphanumeric with hyphens only" });
|
|
5228
5171
|
}
|
|
5229
|
-
|
|
5172
|
+
const exists = await commandExists(configDir, body.metadata.id);
|
|
5173
|
+
if (exists) {
|
|
5230
5174
|
return res.status(409).json({ error: "A command with this ID already exists" });
|
|
5231
5175
|
}
|
|
5232
5176
|
await saveCommand(configDir, body);
|
|
@@ -5234,15 +5178,12 @@ function createCommandRoutes(configDir) {
|
|
|
5234
5178
|
});
|
|
5235
5179
|
router.put("/:id", async (req, res) => {
|
|
5236
5180
|
const { id } = req.params;
|
|
5237
|
-
if (!await commandExists(configDir, id)) {
|
|
5238
|
-
return res.status(404).json({ error: "Command not found" });
|
|
5239
|
-
}
|
|
5240
|
-
const body = req.body;
|
|
5241
5181
|
const commands = await loadAllCommands(configDir);
|
|
5242
5182
|
const existing = findCommandById(id, commands);
|
|
5243
5183
|
if (!existing) {
|
|
5244
5184
|
return res.status(404).json({ error: "Command not found" });
|
|
5245
5185
|
}
|
|
5186
|
+
const body = req.body;
|
|
5246
5187
|
const updated = {
|
|
5247
5188
|
metadata: { ...existing.metadata, ...body.metadata, id },
|
|
5248
5189
|
prompt: body.prompt ?? existing.prompt
|
|
@@ -5252,12 +5193,28 @@ function createCommandRoutes(configDir) {
|
|
|
5252
5193
|
});
|
|
5253
5194
|
router.delete("/:id", async (req, res) => {
|
|
5254
5195
|
const { id } = req.params;
|
|
5255
|
-
const
|
|
5256
|
-
if (!
|
|
5257
|
-
return res.status(
|
|
5196
|
+
const result = await deleteCommand(configDir, id);
|
|
5197
|
+
if (!result.success) {
|
|
5198
|
+
return res.status(403).json({ error: result.reason ?? "Cannot delete this command" });
|
|
5258
5199
|
}
|
|
5259
5200
|
res.json({ success: true });
|
|
5260
5201
|
});
|
|
5202
|
+
router.post("/:id/duplicate", async (req, res) => {
|
|
5203
|
+
const { id } = req.params;
|
|
5204
|
+
const defaults = await loadDefaultCommands();
|
|
5205
|
+
const userItems = await loadUserCommands(configDir);
|
|
5206
|
+
const source = defaults.find((c) => c.metadata.id === id) ?? userItems.find((c) => c.metadata.id === id);
|
|
5207
|
+
if (!source) {
|
|
5208
|
+
return res.status(404).json({ error: "Command not found" });
|
|
5209
|
+
}
|
|
5210
|
+
const newId = `${id}-copy-${Date.now()}`;
|
|
5211
|
+
const duplicated = {
|
|
5212
|
+
metadata: { ...source.metadata, id: newId, name: `${source.metadata.name} (copy)` },
|
|
5213
|
+
prompt: source.prompt
|
|
5214
|
+
};
|
|
5215
|
+
await saveCommand(configDir, duplicated);
|
|
5216
|
+
res.status(201).json(duplicated);
|
|
5217
|
+
});
|
|
5261
5218
|
return router;
|
|
5262
5219
|
}
|
|
5263
5220
|
|
|
@@ -5266,33 +5223,29 @@ import { Router as Router3 } from "express";
|
|
|
5266
5223
|
function createAgentRoutes(configDir) {
|
|
5267
5224
|
const router = Router3();
|
|
5268
5225
|
router.get("/", async (_req, res) => {
|
|
5269
|
-
const [
|
|
5270
|
-
|
|
5271
|
-
|
|
5272
|
-
getModifiedDefaultAgentIds(configDir)
|
|
5226
|
+
const [defaults, userItems] = await Promise.all([
|
|
5227
|
+
loadDefaultAgents(),
|
|
5228
|
+
loadUserAgents(configDir)
|
|
5273
5229
|
]);
|
|
5230
|
+
const overrideIds = computeOverrideIds(defaults, userItems);
|
|
5274
5231
|
res.json({
|
|
5275
|
-
|
|
5276
|
-
|
|
5277
|
-
|
|
5232
|
+
defaults: defaults.map((a) => a.metadata),
|
|
5233
|
+
userItems: userItems.map((a) => a.metadata),
|
|
5234
|
+
overrideIds
|
|
5278
5235
|
});
|
|
5279
5236
|
});
|
|
5237
|
+
router.get("/defaults/:id", async (req, res) => {
|
|
5238
|
+
const { id } = req.params;
|
|
5239
|
+
const content = await getDefaultAgentContent(id);
|
|
5240
|
+
if (!content) {
|
|
5241
|
+
return res.status(404).json({ error: "Default agent not found" });
|
|
5242
|
+
}
|
|
5243
|
+
res.json(content);
|
|
5244
|
+
});
|
|
5280
5245
|
router.get("/default-ids", async (_req, res) => {
|
|
5281
5246
|
const ids = await getDefaultAgentIds();
|
|
5282
5247
|
res.json({ ids });
|
|
5283
5248
|
});
|
|
5284
|
-
router.post("/restore-all-defaults", async (_req, res) => {
|
|
5285
|
-
const count = await restoreAllDefaultAgents(configDir);
|
|
5286
|
-
res.json({ success: true, count });
|
|
5287
|
-
});
|
|
5288
|
-
router.post("/:id/restore-default", async (req, res) => {
|
|
5289
|
-
const { id } = req.params;
|
|
5290
|
-
const restored = await restoreDefaultAgent(configDir, id);
|
|
5291
|
-
if (!restored) {
|
|
5292
|
-
return res.status(404).json({ error: "No bundled default found for this agent" });
|
|
5293
|
-
}
|
|
5294
|
-
res.json({ success: true });
|
|
5295
|
-
});
|
|
5296
5249
|
router.get("/:id", async (req, res) => {
|
|
5297
5250
|
const { id } = req.params;
|
|
5298
5251
|
const agents = await loadAllAgents(configDir);
|
|
@@ -5307,7 +5260,8 @@ function createAgentRoutes(configDir) {
|
|
|
5307
5260
|
if (!body?.metadata?.id || !body?.prompt) {
|
|
5308
5261
|
return res.status(400).json({ error: "Missing required fields: metadata.id, prompt" });
|
|
5309
5262
|
}
|
|
5310
|
-
|
|
5263
|
+
const exists = await agentExists(configDir, body.metadata.id);
|
|
5264
|
+
if (exists) {
|
|
5311
5265
|
return res.status(409).json({ error: "An agent with this ID already exists" });
|
|
5312
5266
|
}
|
|
5313
5267
|
await saveAgent(configDir, body);
|
|
@@ -5333,12 +5287,28 @@ function createAgentRoutes(configDir) {
|
|
|
5333
5287
|
});
|
|
5334
5288
|
router.delete("/:id", async (req, res) => {
|
|
5335
5289
|
const { id } = req.params;
|
|
5336
|
-
const
|
|
5337
|
-
if (!
|
|
5338
|
-
return res.status(
|
|
5290
|
+
const result = await deleteAgent(configDir, id);
|
|
5291
|
+
if (!result.success) {
|
|
5292
|
+
return res.status(403).json({ error: result.reason ?? "Cannot delete this agent" });
|
|
5339
5293
|
}
|
|
5340
5294
|
res.json({ success: true });
|
|
5341
5295
|
});
|
|
5296
|
+
router.post("/:id/duplicate", async (req, res) => {
|
|
5297
|
+
const { id } = req.params;
|
|
5298
|
+
const defaults = await loadDefaultAgents();
|
|
5299
|
+
const userItems = await loadUserAgents(configDir);
|
|
5300
|
+
const source = defaults.find((a) => a.metadata.id === id) ?? userItems.find((a) => a.metadata.id === id);
|
|
5301
|
+
if (!source) {
|
|
5302
|
+
return res.status(404).json({ error: "Agent not found" });
|
|
5303
|
+
}
|
|
5304
|
+
const newId = `${id}-copy-${Date.now()}`;
|
|
5305
|
+
const duplicated = {
|
|
5306
|
+
metadata: { ...source.metadata, id: newId, name: `${source.metadata.name} (copy)` },
|
|
5307
|
+
prompt: source.prompt
|
|
5308
|
+
};
|
|
5309
|
+
await saveAgent(configDir, duplicated);
|
|
5310
|
+
res.status(201).json(duplicated);
|
|
5311
|
+
});
|
|
5342
5312
|
return router;
|
|
5343
5313
|
}
|
|
5344
5314
|
|
|
@@ -5347,37 +5317,33 @@ import { Router as Router4 } from "express";
|
|
|
5347
5317
|
function createWorkflowRoutes(configDir, config) {
|
|
5348
5318
|
const router = Router4();
|
|
5349
5319
|
router.get("/", async (_req, res) => {
|
|
5350
|
-
const [
|
|
5351
|
-
|
|
5352
|
-
|
|
5353
|
-
getModifiedDefaultWorkflowIds(configDir)
|
|
5320
|
+
const [defaults, userItems] = await Promise.all([
|
|
5321
|
+
loadDefaultWorkflows(),
|
|
5322
|
+
loadUserWorkflows(configDir)
|
|
5354
5323
|
]);
|
|
5324
|
+
const overrideIds = computeOverrideIds(defaults, userItems);
|
|
5355
5325
|
res.json({
|
|
5356
|
-
|
|
5326
|
+
defaults: defaults.map((p) => ({ ...p.metadata, startCondition: p.startCondition })),
|
|
5327
|
+
userItems: userItems.map((p) => ({ ...p.metadata, startCondition: p.startCondition })),
|
|
5357
5328
|
activeWorkflowId: config.activeWorkflowId ?? "default",
|
|
5358
|
-
|
|
5359
|
-
modifiedIds
|
|
5329
|
+
overrideIds
|
|
5360
5330
|
});
|
|
5361
5331
|
});
|
|
5362
5332
|
router.get("/template-variables", (_req, res) => {
|
|
5363
5333
|
res.json({ variables: TEMPLATE_VARIABLES });
|
|
5364
5334
|
});
|
|
5335
|
+
router.get("/defaults/:id", async (req, res) => {
|
|
5336
|
+
const { id } = req.params;
|
|
5337
|
+
const content = await getDefaultWorkflowContent(id);
|
|
5338
|
+
if (!content) {
|
|
5339
|
+
return res.status(404).json({ error: "Default workflow not found" });
|
|
5340
|
+
}
|
|
5341
|
+
res.json(content);
|
|
5342
|
+
});
|
|
5365
5343
|
router.get("/default-ids", async (_req, res) => {
|
|
5366
5344
|
const ids = await getDefaultWorkflowIds();
|
|
5367
5345
|
res.json({ ids });
|
|
5368
5346
|
});
|
|
5369
|
-
router.post("/restore-all-defaults", async (_req, res) => {
|
|
5370
|
-
const count = await restoreAllDefaultWorkflows(configDir);
|
|
5371
|
-
res.json({ success: true, count });
|
|
5372
|
-
});
|
|
5373
|
-
router.post("/:id/restore-default", async (req, res) => {
|
|
5374
|
-
const { id } = req.params;
|
|
5375
|
-
const restored = await restoreDefaultWorkflow(configDir, id);
|
|
5376
|
-
if (!restored) {
|
|
5377
|
-
return res.status(404).json({ error: "No bundled default found for this workflow" });
|
|
5378
|
-
}
|
|
5379
|
-
res.json({ success: true });
|
|
5380
|
-
});
|
|
5381
5347
|
router.get("/:id", async (req, res) => {
|
|
5382
5348
|
const { id } = req.params;
|
|
5383
5349
|
const workflows = await loadAllWorkflows(configDir);
|
|
@@ -5392,7 +5358,8 @@ function createWorkflowRoutes(configDir, config) {
|
|
|
5392
5358
|
if (!body?.metadata?.id || !body?.steps?.length) {
|
|
5393
5359
|
return res.status(400).json({ error: "Missing required fields: metadata.id, steps" });
|
|
5394
5360
|
}
|
|
5395
|
-
|
|
5361
|
+
const exists = await workflowExists(configDir, body.metadata.id);
|
|
5362
|
+
if (exists) {
|
|
5396
5363
|
return res.status(409).json({ error: "A workflow with this ID already exists" });
|
|
5397
5364
|
}
|
|
5398
5365
|
await saveWorkflow(configDir, body);
|
|
@@ -5400,7 +5367,9 @@ function createWorkflowRoutes(configDir, config) {
|
|
|
5400
5367
|
});
|
|
5401
5368
|
router.put("/:id", async (req, res) => {
|
|
5402
5369
|
const { id } = req.params;
|
|
5403
|
-
|
|
5370
|
+
const workflows = await loadAllWorkflows(configDir);
|
|
5371
|
+
const existing = findWorkflowById(id, workflows);
|
|
5372
|
+
if (!existing) {
|
|
5404
5373
|
return res.status(404).json({ error: "Workflow not found" });
|
|
5405
5374
|
}
|
|
5406
5375
|
const body = req.body;
|
|
@@ -5413,14 +5382,27 @@ function createWorkflowRoutes(configDir, config) {
|
|
|
5413
5382
|
});
|
|
5414
5383
|
router.delete("/:id", async (req, res) => {
|
|
5415
5384
|
const { id } = req.params;
|
|
5416
|
-
|
|
5417
|
-
|
|
5385
|
+
const result = await deleteWorkflow(configDir, id);
|
|
5386
|
+
if (!result.success) {
|
|
5387
|
+
return res.status(403).json({ error: result.reason ?? "Cannot delete this workflow" });
|
|
5418
5388
|
}
|
|
5419
|
-
|
|
5420
|
-
|
|
5389
|
+
res.json({ success: true });
|
|
5390
|
+
});
|
|
5391
|
+
router.post("/:id/duplicate", async (req, res) => {
|
|
5392
|
+
const { id } = req.params;
|
|
5393
|
+
const defaults = await loadDefaultWorkflows();
|
|
5394
|
+
const userItems = await loadUserWorkflows(configDir);
|
|
5395
|
+
const source = defaults.find((w) => w.metadata.id === id) ?? userItems.find((w) => w.metadata.id === id);
|
|
5396
|
+
if (!source) {
|
|
5421
5397
|
return res.status(404).json({ error: "Workflow not found" });
|
|
5422
5398
|
}
|
|
5423
|
-
|
|
5399
|
+
const newId = `${id}-copy-${Date.now()}`;
|
|
5400
|
+
const duplicated = {
|
|
5401
|
+
...source,
|
|
5402
|
+
metadata: { ...source.metadata, id: newId, name: `${source.metadata.name} (copy)` }
|
|
5403
|
+
};
|
|
5404
|
+
await saveWorkflow(configDir, duplicated);
|
|
5405
|
+
res.status(201).json(duplicated);
|
|
5424
5406
|
});
|
|
5425
5407
|
return router;
|
|
5426
5408
|
}
|
|
@@ -5544,7 +5526,7 @@ function createTerminalRoutes() {
|
|
|
5544
5526
|
}
|
|
5545
5527
|
|
|
5546
5528
|
// src/constants.ts
|
|
5547
|
-
var VERSION = "1.6.
|
|
5529
|
+
var VERSION = "1.6.16";
|
|
5548
5530
|
|
|
5549
5531
|
// src/server/index.ts
|
|
5550
5532
|
var __dirname2 = dirname5(fileURLToPath4(import.meta.url));
|
|
@@ -5555,10 +5537,6 @@ async function createServerHandle(config) {
|
|
|
5555
5537
|
const db = initDatabase(config);
|
|
5556
5538
|
initEventStore(db);
|
|
5557
5539
|
const configDir = getGlobalConfigDir(config.mode ?? "production");
|
|
5558
|
-
await ensureDefaultSkills(configDir);
|
|
5559
|
-
await ensureDefaultCommands(configDir);
|
|
5560
|
-
await ensureDefaultAgents(configDir);
|
|
5561
|
-
await ensureDefaultWorkflows(configDir);
|
|
5562
5540
|
const providerManager = createProviderManager(config);
|
|
5563
5541
|
const sessionManager = new SessionManager(providerManager);
|
|
5564
5542
|
const useMock = process.env["OPENFOX_MOCK_LLM"] === "true";
|
|
@@ -5709,7 +5687,7 @@ async function createServerHandle(config) {
|
|
|
5709
5687
|
res.json({ success: true });
|
|
5710
5688
|
});
|
|
5711
5689
|
app.get("/api/sessions", async (req, res) => {
|
|
5712
|
-
const { getRecentUserPromptsForSession } = await import("./events-
|
|
5690
|
+
const { getRecentUserPromptsForSession } = await import("./events-2ETDOE5B.js");
|
|
5713
5691
|
const projectId = req.query["projectId"];
|
|
5714
5692
|
const limit = Math.min(parseInt(req.query["limit"]) || 20, 100);
|
|
5715
5693
|
const offset = parseInt(req.query["offset"]) || 0;
|
|
@@ -5742,8 +5720,8 @@ async function createServerHandle(config) {
|
|
|
5742
5720
|
res.status(201).json({ session });
|
|
5743
5721
|
});
|
|
5744
5722
|
app.get("/api/sessions/:id", async (req, res) => {
|
|
5745
|
-
const { getEventStore: getEventStore2 } = await import("./events-
|
|
5746
|
-
const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2 } = await import("./folding-
|
|
5723
|
+
const { getEventStore: getEventStore2 } = await import("./events-2ETDOE5B.js");
|
|
5724
|
+
const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2 } = await import("./folding-M7FMUBOL.js");
|
|
5747
5725
|
const session = sessionManager.getSession(req.params.id);
|
|
5748
5726
|
if (!session) {
|
|
5749
5727
|
return res.status(404).json({ error: "Session not found" });
|
|
@@ -5773,8 +5751,8 @@ async function createServerHandle(config) {
|
|
|
5773
5751
|
res.json({ success: true });
|
|
5774
5752
|
});
|
|
5775
5753
|
app.post("/api/sessions/:id/provider", async (req, res) => {
|
|
5776
|
-
const { getEventStore: getEventStore2 } = await import("./events-
|
|
5777
|
-
const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2 } = await import("./folding-
|
|
5754
|
+
const { getEventStore: getEventStore2 } = await import("./events-2ETDOE5B.js");
|
|
5755
|
+
const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2 } = await import("./folding-M7FMUBOL.js");
|
|
5778
5756
|
const sessionId = req.params.id;
|
|
5779
5757
|
const session = sessionManager.getSession(sessionId);
|
|
5780
5758
|
if (!session) {
|
|
@@ -5785,7 +5763,7 @@ async function createServerHandle(config) {
|
|
|
5785
5763
|
return res.status(400).json({ error: "providerId is required" });
|
|
5786
5764
|
}
|
|
5787
5765
|
sessionManager.setSessionProvider(sessionId, providerId, model ?? "auto");
|
|
5788
|
-
const { loadGlobalConfig, saveGlobalConfig, setDefaultModelSelection } = await import("./config-
|
|
5766
|
+
const { loadGlobalConfig, saveGlobalConfig, setDefaultModelSelection } = await import("./config-67AX6CNS.js");
|
|
5789
5767
|
const globalConfig = await loadGlobalConfig(config.mode ?? "production");
|
|
5790
5768
|
const updatedConfig = setDefaultModelSelection(globalConfig, providerId, model ?? "auto");
|
|
5791
5769
|
await saveGlobalConfig(config.mode ?? "production", updatedConfig);
|
|
@@ -5811,8 +5789,8 @@ async function createServerHandle(config) {
|
|
|
5811
5789
|
res.json({ success: true });
|
|
5812
5790
|
});
|
|
5813
5791
|
app.put("/api/sessions/:id/mode", async (req, res) => {
|
|
5814
|
-
const { getEventStore: getEventStore2 } = await import("./events-
|
|
5815
|
-
const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2 } = await import("./folding-
|
|
5792
|
+
const { getEventStore: getEventStore2 } = await import("./events-2ETDOE5B.js");
|
|
5793
|
+
const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2 } = await import("./folding-M7FMUBOL.js");
|
|
5816
5794
|
const sessionId = req.params.id;
|
|
5817
5795
|
const session = sessionManager.getSession(sessionId);
|
|
5818
5796
|
if (!session) {
|
|
@@ -5850,13 +5828,13 @@ async function createServerHandle(config) {
|
|
|
5850
5828
|
if (!callId || approved === void 0) {
|
|
5851
5829
|
return res.status(400).json({ error: "callId and approved are required" });
|
|
5852
5830
|
}
|
|
5853
|
-
const { providePathConfirmation: providePathConfirmation2 } = await import("./tools-
|
|
5831
|
+
const { providePathConfirmation: providePathConfirmation2 } = await import("./tools-55YICCVH.js");
|
|
5854
5832
|
const result = providePathConfirmation2(callId, approved, alwaysAllow);
|
|
5855
5833
|
if (!result.found) {
|
|
5856
5834
|
return res.status(404).json({ error: "No pending path confirmation with that ID" });
|
|
5857
5835
|
}
|
|
5858
|
-
const { getEventStore: getEventStore2 } = await import("./events-
|
|
5859
|
-
const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2, foldPendingConfirmations: foldPendingConfirmations2 } = await import("./folding-
|
|
5836
|
+
const { getEventStore: getEventStore2 } = await import("./events-2ETDOE5B.js");
|
|
5837
|
+
const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2, foldPendingConfirmations: foldPendingConfirmations2 } = await import("./folding-M7FMUBOL.js");
|
|
5860
5838
|
const { createSessionStateMessage: createSessionStateMessage2 } = await import("./protocol-KUKFSV5U.js");
|
|
5861
5839
|
const eventStore = getEventStore2();
|
|
5862
5840
|
const events = eventStore.getEvents(sessionId);
|
|
@@ -5875,7 +5853,7 @@ async function createServerHandle(config) {
|
|
|
5875
5853
|
if (!callId || !answer) {
|
|
5876
5854
|
return res.status(400).json({ error: "callId and answer are required" });
|
|
5877
5855
|
}
|
|
5878
|
-
const { provideAnswer: provideAnswer2 } = await import("./tools-
|
|
5856
|
+
const { provideAnswer: provideAnswer2 } = await import("./tools-55YICCVH.js");
|
|
5879
5857
|
const found = provideAnswer2(callId, answer);
|
|
5880
5858
|
if (!found) {
|
|
5881
5859
|
return res.status(404).json({ error: "No pending question with that ID" });
|
|
@@ -5911,14 +5889,14 @@ async function createServerHandle(config) {
|
|
|
5911
5889
|
if (!session) {
|
|
5912
5890
|
return res.status(404).json({ error: "Session not found" });
|
|
5913
5891
|
}
|
|
5914
|
-
const { stopSessionExecution } = await import("./chat-handler-
|
|
5915
|
-
const { cancelQuestionsForSession: cancelQuestionsForSession2, cancelPathConfirmationsForSession: cancelPathConfirmationsForSession2 } = await import("./tools-
|
|
5892
|
+
const { stopSessionExecution } = await import("./chat-handler-IY2XVOO6.js");
|
|
5893
|
+
const { cancelQuestionsForSession: cancelQuestionsForSession2, cancelPathConfirmationsForSession: cancelPathConfirmationsForSession2 } = await import("./tools-55YICCVH.js");
|
|
5916
5894
|
stopSessionExecution(sessionId, sessionManager);
|
|
5917
5895
|
abortSession(sessionId);
|
|
5918
5896
|
cancelQuestionsForSession2(sessionId, "Session stopped by user");
|
|
5919
5897
|
cancelPathConfirmationsForSession2(sessionId, "Session stopped by user");
|
|
5920
5898
|
sessionManager.clearMessageQueue(sessionId);
|
|
5921
|
-
const eventStore = (await import("./events-
|
|
5899
|
+
const eventStore = (await import("./events-2ETDOE5B.js")).getEventStore();
|
|
5922
5900
|
eventStore.append(sessionId, { type: "running.changed", data: { isRunning: false } });
|
|
5923
5901
|
res.json({ success: true });
|
|
5924
5902
|
});
|
|
@@ -5970,7 +5948,7 @@ async function createServerHandle(config) {
|
|
|
5970
5948
|
let visionFallback;
|
|
5971
5949
|
let globalWorkdir;
|
|
5972
5950
|
try {
|
|
5973
|
-
const { loadGlobalConfig, getVisionFallback } = await import("./config-
|
|
5951
|
+
const { loadGlobalConfig, getVisionFallback } = await import("./config-67AX6CNS.js");
|
|
5974
5952
|
const globalConfig = await loadGlobalConfig(config.mode ?? "production");
|
|
5975
5953
|
const fallback = getVisionFallback(globalConfig);
|
|
5976
5954
|
if (fallback) {
|
|
@@ -6049,7 +6027,7 @@ async function createServerHandle(config) {
|
|
|
6049
6027
|
return res.status(400).json({ error: "name, url, and backend are required" });
|
|
6050
6028
|
}
|
|
6051
6029
|
try {
|
|
6052
|
-
const { loadGlobalConfig, saveGlobalConfig, addProvider, setDefaultModelSelection } = await import("./config-
|
|
6030
|
+
const { loadGlobalConfig, saveGlobalConfig, addProvider, setDefaultModelSelection } = await import("./config-67AX6CNS.js");
|
|
6053
6031
|
const globalConfig = await loadGlobalConfig(config.mode ?? "production");
|
|
6054
6032
|
const providerBackend = backend;
|
|
6055
6033
|
const configWithProvider = addProvider(globalConfig, {
|
|
@@ -6082,7 +6060,7 @@ async function createServerHandle(config) {
|
|
|
6082
6060
|
app.post("/api/init/config", async (req, res) => {
|
|
6083
6061
|
const { workdir, visionFallback } = req.body;
|
|
6084
6062
|
try {
|
|
6085
|
-
const { loadGlobalConfig, saveGlobalConfig } = await import("./config-
|
|
6063
|
+
const { loadGlobalConfig, saveGlobalConfig } = await import("./config-67AX6CNS.js");
|
|
6086
6064
|
const globalConfig = await loadGlobalConfig(config.mode ?? "production");
|
|
6087
6065
|
const updatedConfig = {
|
|
6088
6066
|
...globalConfig,
|
|
@@ -6110,7 +6088,7 @@ async function createServerHandle(config) {
|
|
|
6110
6088
|
});
|
|
6111
6089
|
app.delete("/api/providers/:id", async (req, res) => {
|
|
6112
6090
|
const { id } = req.params;
|
|
6113
|
-
const { loadGlobalConfig, saveGlobalConfig, removeProvider } = await import("./config-
|
|
6091
|
+
const { loadGlobalConfig, saveGlobalConfig, removeProvider } = await import("./config-67AX6CNS.js");
|
|
6114
6092
|
const globalConfig = await loadGlobalConfig(config.mode ?? "production");
|
|
6115
6093
|
const updatedConfig = removeProvider(globalConfig, id);
|
|
6116
6094
|
await saveGlobalConfig(config.mode ?? "production", updatedConfig);
|
|
@@ -6130,7 +6108,7 @@ async function createServerHandle(config) {
|
|
|
6130
6108
|
return res.status(400).json({ error: result.error });
|
|
6131
6109
|
}
|
|
6132
6110
|
const llmClient = getLLMClient();
|
|
6133
|
-
const { loadGlobalConfig, saveGlobalConfig, setDefaultModelSelection } = await import("./config-
|
|
6111
|
+
const { loadGlobalConfig, saveGlobalConfig, setDefaultModelSelection } = await import("./config-67AX6CNS.js");
|
|
6134
6112
|
const globalConfig = await loadGlobalConfig(config.mode ?? "production");
|
|
6135
6113
|
const updatedConfig = setDefaultModelSelection(globalConfig, id, llmClient.getModel());
|
|
6136
6114
|
await saveGlobalConfig(config.mode ?? "production", updatedConfig);
|
|
@@ -6151,7 +6129,7 @@ async function createServerHandle(config) {
|
|
|
6151
6129
|
if (!result.success) {
|
|
6152
6130
|
return res.status(400).json({ error: result.error });
|
|
6153
6131
|
}
|
|
6154
|
-
const { loadGlobalConfig, saveGlobalConfig } = await import("./config-
|
|
6132
|
+
const { loadGlobalConfig, saveGlobalConfig } = await import("./config-67AX6CNS.js");
|
|
6155
6133
|
const globalConfig = await loadGlobalConfig(config.mode ?? "production");
|
|
6156
6134
|
const updatedProviders = providerManager.getProviders();
|
|
6157
6135
|
const updatedConfig = {
|
|
@@ -6232,7 +6210,7 @@ async function createServerHandle(config) {
|
|
|
6232
6210
|
const entries = await import("fs/promises").then((m) => m.readdir(resolvedPath, { withFileTypes: true }));
|
|
6233
6211
|
const directories = entries.filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => ({
|
|
6234
6212
|
name: entry.name,
|
|
6235
|
-
path:
|
|
6213
|
+
path: join6(resolvedPath, entry.name)
|
|
6236
6214
|
})).sort((a, b) => a.name.localeCompare(b.name));
|
|
6237
6215
|
const parent = dirname5(resolvedPath);
|
|
6238
6216
|
const hasParent = parent !== resolvedPath;
|
|
@@ -6279,7 +6257,7 @@ async function createServerHandle(config) {
|
|
|
6279
6257
|
}
|
|
6280
6258
|
});
|
|
6281
6259
|
app.get("/fox.svg", (_req, res) => {
|
|
6282
|
-
readFile4(
|
|
6260
|
+
readFile4(join6(webDir, "fox.svg")).then((content) => {
|
|
6283
6261
|
res.set("Content-Type", "image/svg+xml");
|
|
6284
6262
|
res.send(content);
|
|
6285
6263
|
}).catch(() => {
|
|
@@ -6288,7 +6266,7 @@ async function createServerHandle(config) {
|
|
|
6288
6266
|
});
|
|
6289
6267
|
app.use(
|
|
6290
6268
|
"/sounds",
|
|
6291
|
-
express.static(
|
|
6269
|
+
express.static(join6(webDir, "public", "sounds"), {
|
|
6292
6270
|
setHeaders: (res) => {
|
|
6293
6271
|
res.set("Content-Type", "audio/mpeg");
|
|
6294
6272
|
}
|
|
@@ -6298,7 +6276,7 @@ async function createServerHandle(config) {
|
|
|
6298
6276
|
if (req.path.startsWith("/api/")) {
|
|
6299
6277
|
return;
|
|
6300
6278
|
}
|
|
6301
|
-
readFile4(
|
|
6279
|
+
readFile4(join6(webDir, "index.html"), "utf-8").then((indexHtml) => viteServer.transformIndexHtml(req.originalUrl, indexHtml)).then((transformed) => res.send(transformed)).catch((err) => {
|
|
6302
6280
|
logger.error("Error serving index.html", { error: err });
|
|
6303
6281
|
res.status(500).send("Server error");
|
|
6304
6282
|
});
|
|
@@ -6309,7 +6287,7 @@ async function createServerHandle(config) {
|
|
|
6309
6287
|
const distWebDir = resolve(__dirname2, "web");
|
|
6310
6288
|
app.use(
|
|
6311
6289
|
"/assets",
|
|
6312
|
-
express.static(
|
|
6290
|
+
express.static(join6(distWebDir, "assets"), {
|
|
6313
6291
|
setHeaders: (res, filepath) => {
|
|
6314
6292
|
if (filepath.endsWith(".css")) {
|
|
6315
6293
|
res.set("Content-Type", "text/css");
|
|
@@ -6317,11 +6295,11 @@ async function createServerHandle(config) {
|
|
|
6317
6295
|
}
|
|
6318
6296
|
})
|
|
6319
6297
|
);
|
|
6320
|
-
app.use("/manifest.webmanifest", express.static(
|
|
6321
|
-
app.use("/registerSW.js", express.static(
|
|
6322
|
-
app.use("/sw.js", express.static(
|
|
6298
|
+
app.use("/manifest.webmanifest", express.static(join6(distWebDir, "manifest.webmanifest")));
|
|
6299
|
+
app.use("/registerSW.js", express.static(join6(distWebDir, "registerSW.js")));
|
|
6300
|
+
app.use("/sw.js", express.static(join6(distWebDir, "sw.js")));
|
|
6323
6301
|
app.get("/fox.svg", (_req, res) => {
|
|
6324
|
-
readFile4(
|
|
6302
|
+
readFile4(join6(distWebDir, "fox.svg")).then((content) => {
|
|
6325
6303
|
res.set("Content-Type", "image/svg+xml");
|
|
6326
6304
|
res.send(content);
|
|
6327
6305
|
}).catch(() => {
|
|
@@ -6330,14 +6308,14 @@ async function createServerHandle(config) {
|
|
|
6330
6308
|
});
|
|
6331
6309
|
app.use(
|
|
6332
6310
|
"/sounds",
|
|
6333
|
-
express.static(
|
|
6311
|
+
express.static(join6(distWebDir, "sounds"), {
|
|
6334
6312
|
setHeaders: (res) => {
|
|
6335
6313
|
res.set("Content-Type", "audio/mpeg");
|
|
6336
6314
|
}
|
|
6337
6315
|
})
|
|
6338
6316
|
);
|
|
6339
6317
|
app.get("/", (_req, res) => {
|
|
6340
|
-
readFile4(
|
|
6318
|
+
readFile4(join6(distWebDir, "index.html"), "utf-8").then((content) => res.send(content)).catch(() => {
|
|
6341
6319
|
res.status(404).send("Web UI not built. Run `npm run build:web`");
|
|
6342
6320
|
});
|
|
6343
6321
|
});
|
|
@@ -6345,7 +6323,7 @@ async function createServerHandle(config) {
|
|
|
6345
6323
|
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") {
|
|
6346
6324
|
return;
|
|
6347
6325
|
}
|
|
6348
|
-
readFile4(
|
|
6326
|
+
readFile4(join6(distWebDir, "index.html"), "utf-8").then((content) => res.send(content)).catch(() => {
|
|
6349
6327
|
res.status(404).send("Web UI not built");
|
|
6350
6328
|
});
|
|
6351
6329
|
});
|
|
@@ -6360,7 +6338,7 @@ async function createServerHandle(config) {
|
|
|
6360
6338
|
providerManager
|
|
6361
6339
|
);
|
|
6362
6340
|
const wss = wssExports.wss;
|
|
6363
|
-
const { QueueProcessor } = await import("./processor-
|
|
6341
|
+
const { QueueProcessor } = await import("./processor-VUEJM73B.js");
|
|
6364
6342
|
const queueProcessor = new QueueProcessor({
|
|
6365
6343
|
sessionManager,
|
|
6366
6344
|
providerManager,
|
|
@@ -6433,4 +6411,4 @@ export {
|
|
|
6433
6411
|
createServerHandle,
|
|
6434
6412
|
createServer
|
|
6435
6413
|
};
|
|
6436
|
-
//# sourceMappingURL=chunk-
|
|
6414
|
+
//# sourceMappingURL=chunk-NN65D5SI.js.map
|