@agiflowai/scaffold-mcp 1.0.21 → 1.0.22
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/cli.cjs +23 -22
- package/dist/cli.mjs +6 -5
- package/dist/index.cjs +12 -11
- package/dist/index.mjs +2 -1
- package/dist/stdio-BqcCsHuC.mjs +331 -0
- package/dist/stdio-D8getFsj.cjs +350 -0
- package/dist/{stdio-Boc4SGGT.mjs → tools-DRfJ2LZc.mjs} +1 -330
- package/dist/{stdio-Bw7Hyv3X.cjs → tools-S18iKO9I.cjs} +0 -348
- package/dist/{useScaffoldMethod-BR3ESqor.cjs → useScaffoldMethod-CmnKY0Vu.cjs} +80 -40
- package/dist/{useScaffoldMethod-DlrzH-3H.mjs → useScaffoldMethod-blx199pL.mjs} +80 -40
- package/package.json +5 -5
- /package/dist/{phantomCodeCheck-BXQonrXo.mjs → phantomCodeCheck-BwQWRJ9Q.mjs} +0 -0
- /package/dist/{phantomCodeCheck-DNkWyMRE.cjs → phantomCodeCheck-DhzeymO-.cjs} +0 -0
- /package/dist/{useScaffoldMethod-DaAZTyIM.mjs → useScaffoldMethod-BE2tHUMc.mjs} +0 -0
- /package/dist/{useScaffoldMethod-CJG7ngkT.cjs → useScaffoldMethod-CejnYNDD.cjs} +0 -0
|
@@ -11,13 +11,6 @@ let node_fs_promises = require("node:fs/promises");
|
|
|
11
11
|
node_fs_promises = require_ListScaffoldingMethodsTool.__toESM(node_fs_promises);
|
|
12
12
|
let node_os = require("node:os");
|
|
13
13
|
node_os = require_ListScaffoldingMethodsTool.__toESM(node_os);
|
|
14
|
-
let node_crypto = require("node:crypto");
|
|
15
|
-
let __modelcontextprotocol_sdk_server_streamableHttp_js = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
|
|
16
|
-
let __modelcontextprotocol_sdk_types_js = require("@modelcontextprotocol/sdk/types.js");
|
|
17
|
-
let express = require("express");
|
|
18
|
-
express = require_ListScaffoldingMethodsTool.__toESM(express);
|
|
19
|
-
let __modelcontextprotocol_sdk_server_sse_js = require("@modelcontextprotocol/sdk/server/sse.js");
|
|
20
|
-
let __modelcontextprotocol_sdk_server_stdio_js = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
21
14
|
|
|
22
15
|
//#region src/services/BoilerplateGeneratorService.ts
|
|
23
16
|
/**
|
|
@@ -1527,329 +1520,6 @@ Parameters:
|
|
|
1527
1520
|
}
|
|
1528
1521
|
};
|
|
1529
1522
|
|
|
1530
|
-
//#endregion
|
|
1531
|
-
//#region src/transports/http.ts
|
|
1532
|
-
/**
|
|
1533
|
-
* HTTP session manager
|
|
1534
|
-
*/
|
|
1535
|
-
var HttpFullSessionManager = class {
|
|
1536
|
-
sessions = /* @__PURE__ */ new Map();
|
|
1537
|
-
getSession(sessionId) {
|
|
1538
|
-
return this.sessions.get(sessionId);
|
|
1539
|
-
}
|
|
1540
|
-
setSession(sessionId, transport, server) {
|
|
1541
|
-
this.sessions.set(sessionId, {
|
|
1542
|
-
transport,
|
|
1543
|
-
server
|
|
1544
|
-
});
|
|
1545
|
-
}
|
|
1546
|
-
deleteSession(sessionId) {
|
|
1547
|
-
const session = this.sessions.get(sessionId);
|
|
1548
|
-
if (session) session.server.close();
|
|
1549
|
-
this.sessions.delete(sessionId);
|
|
1550
|
-
}
|
|
1551
|
-
hasSession(sessionId) {
|
|
1552
|
-
return this.sessions.has(sessionId);
|
|
1553
|
-
}
|
|
1554
|
-
clear() {
|
|
1555
|
-
for (const session of this.sessions.values()) session.server.close();
|
|
1556
|
-
this.sessions.clear();
|
|
1557
|
-
}
|
|
1558
|
-
};
|
|
1559
|
-
/**
|
|
1560
|
-
* HTTP transport handler using Streamable HTTP (protocol version 2025-03-26)
|
|
1561
|
-
* Provides stateful session management with resumability support
|
|
1562
|
-
*/
|
|
1563
|
-
var HttpTransportHandler = class {
|
|
1564
|
-
serverFactory;
|
|
1565
|
-
app;
|
|
1566
|
-
server = null;
|
|
1567
|
-
sessionManager;
|
|
1568
|
-
config;
|
|
1569
|
-
constructor(serverFactory, config) {
|
|
1570
|
-
this.serverFactory = typeof serverFactory === "function" ? serverFactory : () => serverFactory;
|
|
1571
|
-
this.app = (0, express.default)();
|
|
1572
|
-
this.sessionManager = new HttpFullSessionManager();
|
|
1573
|
-
this.config = {
|
|
1574
|
-
mode: config.mode,
|
|
1575
|
-
port: config.port ?? 3e3,
|
|
1576
|
-
host: config.host ?? "localhost"
|
|
1577
|
-
};
|
|
1578
|
-
this.setupMiddleware();
|
|
1579
|
-
this.setupRoutes();
|
|
1580
|
-
}
|
|
1581
|
-
setupMiddleware() {
|
|
1582
|
-
this.app.use(express.default.json());
|
|
1583
|
-
}
|
|
1584
|
-
setupRoutes() {
|
|
1585
|
-
this.app.post("/mcp", async (req, res) => {
|
|
1586
|
-
await this.handlePostRequest(req, res);
|
|
1587
|
-
});
|
|
1588
|
-
this.app.get("/mcp", async (req, res) => {
|
|
1589
|
-
await this.handleGetRequest(req, res);
|
|
1590
|
-
});
|
|
1591
|
-
this.app.delete("/mcp", async (req, res) => {
|
|
1592
|
-
await this.handleDeleteRequest(req, res);
|
|
1593
|
-
});
|
|
1594
|
-
this.app.get("/health", (_req, res) => {
|
|
1595
|
-
res.json({
|
|
1596
|
-
status: "ok",
|
|
1597
|
-
transport: "http"
|
|
1598
|
-
});
|
|
1599
|
-
});
|
|
1600
|
-
}
|
|
1601
|
-
async handlePostRequest(req, res) {
|
|
1602
|
-
const sessionId = req.headers["mcp-session-id"];
|
|
1603
|
-
let transport;
|
|
1604
|
-
if (sessionId && this.sessionManager.hasSession(sessionId)) transport = this.sessionManager.getSession(sessionId).transport;
|
|
1605
|
-
else if (!sessionId && (0, __modelcontextprotocol_sdk_types_js.isInitializeRequest)(req.body)) {
|
|
1606
|
-
const mcpServer = this.serverFactory();
|
|
1607
|
-
transport = new __modelcontextprotocol_sdk_server_streamableHttp_js.StreamableHTTPServerTransport({
|
|
1608
|
-
sessionIdGenerator: () => (0, node_crypto.randomUUID)(),
|
|
1609
|
-
enableJsonResponse: true,
|
|
1610
|
-
onsessioninitialized: (sessionId$1) => {
|
|
1611
|
-
this.sessionManager.setSession(sessionId$1, transport, mcpServer);
|
|
1612
|
-
}
|
|
1613
|
-
});
|
|
1614
|
-
transport.onclose = () => {
|
|
1615
|
-
if (transport.sessionId) this.sessionManager.deleteSession(transport.sessionId);
|
|
1616
|
-
};
|
|
1617
|
-
await mcpServer.connect(transport);
|
|
1618
|
-
} else {
|
|
1619
|
-
res.status(400).json({
|
|
1620
|
-
jsonrpc: "2.0",
|
|
1621
|
-
error: {
|
|
1622
|
-
code: -32e3,
|
|
1623
|
-
message: "Bad Request: No valid session ID provided"
|
|
1624
|
-
},
|
|
1625
|
-
id: null
|
|
1626
|
-
});
|
|
1627
|
-
return;
|
|
1628
|
-
}
|
|
1629
|
-
await transport.handleRequest(req, res, req.body);
|
|
1630
|
-
}
|
|
1631
|
-
async handleGetRequest(req, res) {
|
|
1632
|
-
const sessionId = req.headers["mcp-session-id"];
|
|
1633
|
-
if (!sessionId || !this.sessionManager.hasSession(sessionId)) {
|
|
1634
|
-
res.status(400).send("Invalid or missing session ID");
|
|
1635
|
-
return;
|
|
1636
|
-
}
|
|
1637
|
-
await this.sessionManager.getSession(sessionId).transport.handleRequest(req, res);
|
|
1638
|
-
}
|
|
1639
|
-
async handleDeleteRequest(req, res) {
|
|
1640
|
-
const sessionId = req.headers["mcp-session-id"];
|
|
1641
|
-
if (!sessionId || !this.sessionManager.hasSession(sessionId)) {
|
|
1642
|
-
res.status(400).send("Invalid or missing session ID");
|
|
1643
|
-
return;
|
|
1644
|
-
}
|
|
1645
|
-
await this.sessionManager.getSession(sessionId).transport.handleRequest(req, res);
|
|
1646
|
-
this.sessionManager.deleteSession(sessionId);
|
|
1647
|
-
}
|
|
1648
|
-
async start() {
|
|
1649
|
-
return new Promise((resolve, reject) => {
|
|
1650
|
-
try {
|
|
1651
|
-
this.server = this.app.listen(this.config.port, this.config.host, () => {
|
|
1652
|
-
console.error(`Scaffolding MCP server started on http://${this.config.host}:${this.config.port}/mcp`);
|
|
1653
|
-
console.error(`Health check: http://${this.config.host}:${this.config.port}/health`);
|
|
1654
|
-
resolve();
|
|
1655
|
-
});
|
|
1656
|
-
this.server.on("error", (error) => {
|
|
1657
|
-
reject(error);
|
|
1658
|
-
});
|
|
1659
|
-
} catch (error) {
|
|
1660
|
-
reject(error);
|
|
1661
|
-
}
|
|
1662
|
-
});
|
|
1663
|
-
}
|
|
1664
|
-
async stop() {
|
|
1665
|
-
return new Promise((resolve, reject) => {
|
|
1666
|
-
if (this.server) {
|
|
1667
|
-
this.sessionManager.clear();
|
|
1668
|
-
this.server.close((err) => {
|
|
1669
|
-
if (err) reject(err);
|
|
1670
|
-
else {
|
|
1671
|
-
this.server = null;
|
|
1672
|
-
resolve();
|
|
1673
|
-
}
|
|
1674
|
-
});
|
|
1675
|
-
} else resolve();
|
|
1676
|
-
});
|
|
1677
|
-
}
|
|
1678
|
-
getPort() {
|
|
1679
|
-
return this.config.port;
|
|
1680
|
-
}
|
|
1681
|
-
getHost() {
|
|
1682
|
-
return this.config.host;
|
|
1683
|
-
}
|
|
1684
|
-
};
|
|
1685
|
-
|
|
1686
|
-
//#endregion
|
|
1687
|
-
//#region src/transports/sse.ts
|
|
1688
|
-
/**
|
|
1689
|
-
* Session manager for SSE transports
|
|
1690
|
-
*/
|
|
1691
|
-
var SseSessionManager = class {
|
|
1692
|
-
sessions = /* @__PURE__ */ new Map();
|
|
1693
|
-
getSession(sessionId) {
|
|
1694
|
-
return this.sessions.get(sessionId)?.transport;
|
|
1695
|
-
}
|
|
1696
|
-
setSession(sessionId, transport, server) {
|
|
1697
|
-
this.sessions.set(sessionId, {
|
|
1698
|
-
transport,
|
|
1699
|
-
server
|
|
1700
|
-
});
|
|
1701
|
-
}
|
|
1702
|
-
deleteSession(sessionId) {
|
|
1703
|
-
const session = this.sessions.get(sessionId);
|
|
1704
|
-
if (session) session.server.close();
|
|
1705
|
-
this.sessions.delete(sessionId);
|
|
1706
|
-
}
|
|
1707
|
-
hasSession(sessionId) {
|
|
1708
|
-
return this.sessions.has(sessionId);
|
|
1709
|
-
}
|
|
1710
|
-
clear() {
|
|
1711
|
-
for (const session of this.sessions.values()) session.server.close();
|
|
1712
|
-
this.sessions.clear();
|
|
1713
|
-
}
|
|
1714
|
-
};
|
|
1715
|
-
/**
|
|
1716
|
-
* SSE (Server-Sent Events) transport handler
|
|
1717
|
-
* Legacy transport for backwards compatibility (protocol version 2024-11-05)
|
|
1718
|
-
* Uses separate endpoints: /sse for SSE stream (GET) and /messages for client messages (POST)
|
|
1719
|
-
*/
|
|
1720
|
-
var SseTransportHandler = class {
|
|
1721
|
-
serverFactory;
|
|
1722
|
-
app;
|
|
1723
|
-
server = null;
|
|
1724
|
-
sessionManager;
|
|
1725
|
-
config;
|
|
1726
|
-
constructor(serverFactory, config) {
|
|
1727
|
-
this.serverFactory = typeof serverFactory === "function" ? serverFactory : () => serverFactory;
|
|
1728
|
-
this.app = (0, express.default)();
|
|
1729
|
-
this.sessionManager = new SseSessionManager();
|
|
1730
|
-
this.config = {
|
|
1731
|
-
mode: config.mode,
|
|
1732
|
-
port: config.port ?? 3e3,
|
|
1733
|
-
host: config.host ?? "localhost"
|
|
1734
|
-
};
|
|
1735
|
-
this.setupMiddleware();
|
|
1736
|
-
this.setupRoutes();
|
|
1737
|
-
}
|
|
1738
|
-
setupMiddleware() {
|
|
1739
|
-
this.app.use(express.default.json());
|
|
1740
|
-
}
|
|
1741
|
-
setupRoutes() {
|
|
1742
|
-
this.app.get("/sse", async (req, res) => {
|
|
1743
|
-
await this.handleSseConnection(req, res);
|
|
1744
|
-
});
|
|
1745
|
-
this.app.post("/messages", async (req, res) => {
|
|
1746
|
-
await this.handlePostMessage(req, res);
|
|
1747
|
-
});
|
|
1748
|
-
this.app.get("/health", (_req, res) => {
|
|
1749
|
-
res.json({
|
|
1750
|
-
status: "ok",
|
|
1751
|
-
transport: "sse"
|
|
1752
|
-
});
|
|
1753
|
-
});
|
|
1754
|
-
}
|
|
1755
|
-
async handleSseConnection(_req, res) {
|
|
1756
|
-
try {
|
|
1757
|
-
const mcpServer = this.serverFactory();
|
|
1758
|
-
const transport = new __modelcontextprotocol_sdk_server_sse_js.SSEServerTransport("/messages", res);
|
|
1759
|
-
this.sessionManager.setSession(transport.sessionId, transport, mcpServer);
|
|
1760
|
-
res.on("close", () => {
|
|
1761
|
-
this.sessionManager.deleteSession(transport.sessionId);
|
|
1762
|
-
});
|
|
1763
|
-
await mcpServer.connect(transport);
|
|
1764
|
-
console.error(`SSE session established: ${transport.sessionId}`);
|
|
1765
|
-
} catch (error) {
|
|
1766
|
-
console.error("Error handling SSE connection:", error);
|
|
1767
|
-
if (!res.headersSent) res.status(500).send("Internal Server Error");
|
|
1768
|
-
}
|
|
1769
|
-
}
|
|
1770
|
-
async handlePostMessage(req, res) {
|
|
1771
|
-
const sessionId = req.query.sessionId;
|
|
1772
|
-
if (!sessionId) {
|
|
1773
|
-
res.status(400).send("Missing sessionId query parameter");
|
|
1774
|
-
return;
|
|
1775
|
-
}
|
|
1776
|
-
const transport = this.sessionManager.getSession(sessionId);
|
|
1777
|
-
if (!transport) {
|
|
1778
|
-
res.status(404).send("No transport found for sessionId");
|
|
1779
|
-
return;
|
|
1780
|
-
}
|
|
1781
|
-
try {
|
|
1782
|
-
await transport.handlePostMessage(req, res, req.body);
|
|
1783
|
-
} catch (error) {
|
|
1784
|
-
console.error("Error handling post message:", error);
|
|
1785
|
-
if (!res.headersSent) res.status(500).send("Internal Server Error");
|
|
1786
|
-
}
|
|
1787
|
-
}
|
|
1788
|
-
async start() {
|
|
1789
|
-
return new Promise((resolve, reject) => {
|
|
1790
|
-
try {
|
|
1791
|
-
this.server = this.app.listen(this.config.port, this.config.host, () => {
|
|
1792
|
-
console.error(`Scaffolding MCP server started with SSE transport on http://${this.config.host}:${this.config.port}`);
|
|
1793
|
-
console.error(`SSE endpoint: http://${this.config.host}:${this.config.port}/sse`);
|
|
1794
|
-
console.error(`Messages endpoint: http://${this.config.host}:${this.config.port}/messages`);
|
|
1795
|
-
console.error(`Health check: http://${this.config.host}:${this.config.port}/health`);
|
|
1796
|
-
resolve();
|
|
1797
|
-
});
|
|
1798
|
-
this.server.on("error", (error) => {
|
|
1799
|
-
reject(error);
|
|
1800
|
-
});
|
|
1801
|
-
} catch (error) {
|
|
1802
|
-
reject(error);
|
|
1803
|
-
}
|
|
1804
|
-
});
|
|
1805
|
-
}
|
|
1806
|
-
async stop() {
|
|
1807
|
-
return new Promise((resolve, reject) => {
|
|
1808
|
-
if (this.server) {
|
|
1809
|
-
this.sessionManager.clear();
|
|
1810
|
-
this.server.close((err) => {
|
|
1811
|
-
if (err) reject(err);
|
|
1812
|
-
else {
|
|
1813
|
-
this.server = null;
|
|
1814
|
-
resolve();
|
|
1815
|
-
}
|
|
1816
|
-
});
|
|
1817
|
-
} else resolve();
|
|
1818
|
-
});
|
|
1819
|
-
}
|
|
1820
|
-
getPort() {
|
|
1821
|
-
return this.config.port;
|
|
1822
|
-
}
|
|
1823
|
-
getHost() {
|
|
1824
|
-
return this.config.host;
|
|
1825
|
-
}
|
|
1826
|
-
};
|
|
1827
|
-
|
|
1828
|
-
//#endregion
|
|
1829
|
-
//#region src/transports/stdio.ts
|
|
1830
|
-
/**
|
|
1831
|
-
* Stdio transport handler for MCP server
|
|
1832
|
-
* Used for command-line and direct integrations
|
|
1833
|
-
*/
|
|
1834
|
-
var StdioTransportHandler = class {
|
|
1835
|
-
server;
|
|
1836
|
-
transport = null;
|
|
1837
|
-
constructor(server) {
|
|
1838
|
-
this.server = server;
|
|
1839
|
-
}
|
|
1840
|
-
async start() {
|
|
1841
|
-
this.transport = new __modelcontextprotocol_sdk_server_stdio_js.StdioServerTransport();
|
|
1842
|
-
await this.server.connect(this.transport);
|
|
1843
|
-
console.error("Scaffolding MCP server started on stdio");
|
|
1844
|
-
}
|
|
1845
|
-
async stop() {
|
|
1846
|
-
if (this.transport) {
|
|
1847
|
-
await this.transport.close();
|
|
1848
|
-
this.transport = null;
|
|
1849
|
-
}
|
|
1850
|
-
}
|
|
1851
|
-
};
|
|
1852
|
-
|
|
1853
1523
|
//#endregion
|
|
1854
1524
|
Object.defineProperty(exports, 'BoilerplateGeneratorService', {
|
|
1855
1525
|
enumerable: true,
|
|
@@ -1881,12 +1551,6 @@ Object.defineProperty(exports, 'GenerateFeatureScaffoldTool', {
|
|
|
1881
1551
|
return GenerateFeatureScaffoldTool;
|
|
1882
1552
|
}
|
|
1883
1553
|
});
|
|
1884
|
-
Object.defineProperty(exports, 'HttpTransportHandler', {
|
|
1885
|
-
enumerable: true,
|
|
1886
|
-
get: function () {
|
|
1887
|
-
return HttpTransportHandler;
|
|
1888
|
-
}
|
|
1889
|
-
});
|
|
1890
1554
|
Object.defineProperty(exports, 'ListBoilerplatesTool', {
|
|
1891
1555
|
enumerable: true,
|
|
1892
1556
|
get: function () {
|
|
@@ -1899,18 +1563,6 @@ Object.defineProperty(exports, 'ScaffoldGeneratorService', {
|
|
|
1899
1563
|
return ScaffoldGeneratorService;
|
|
1900
1564
|
}
|
|
1901
1565
|
});
|
|
1902
|
-
Object.defineProperty(exports, 'SseTransportHandler', {
|
|
1903
|
-
enumerable: true,
|
|
1904
|
-
get: function () {
|
|
1905
|
-
return SseTransportHandler;
|
|
1906
|
-
}
|
|
1907
|
-
});
|
|
1908
|
-
Object.defineProperty(exports, 'StdioTransportHandler', {
|
|
1909
|
-
enumerable: true,
|
|
1910
|
-
get: function () {
|
|
1911
|
-
return StdioTransportHandler;
|
|
1912
|
-
}
|
|
1913
|
-
});
|
|
1914
1566
|
Object.defineProperty(exports, 'UseBoilerplateTool', {
|
|
1915
1567
|
enumerable: true,
|
|
1916
1568
|
get: function () {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const require_ListScaffoldingMethodsTool = require('./ListScaffoldingMethodsTool-Dnd3E5X_.cjs');
|
|
2
|
+
require('./tools-S18iKO9I.cjs');
|
|
2
3
|
let node_path = require("node:path");
|
|
3
4
|
node_path = require_ListScaffoldingMethodsTool.__toESM(node_path);
|
|
4
5
|
let __agiflowai_aicode_utils = require("@agiflowai/aicode-utils");
|
|
@@ -10,6 +11,22 @@ let __agiflowai_hooks_adapter = require("@agiflowai/hooks-adapter");
|
|
|
10
11
|
|
|
11
12
|
//#region src/hooks/claudeCode/useScaffoldMethod.ts
|
|
12
13
|
/**
|
|
14
|
+
* Type guard for ScaffoldMethodsResponse
|
|
15
|
+
*/
|
|
16
|
+
function isScaffoldMethodsResponse(value) {
|
|
17
|
+
if (typeof value !== "object" || value === null) return false;
|
|
18
|
+
if ("methods" in value && !Array.isArray(value.methods)) return false;
|
|
19
|
+
if ("nextCursor" in value && typeof value.nextCursor !== "string") return false;
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Type guard for PendingScaffoldLogEntry
|
|
24
|
+
*/
|
|
25
|
+
function isPendingScaffoldLogEntry(value) {
|
|
26
|
+
if (typeof value !== "object" || value === null) return false;
|
|
27
|
+
return "scaffoldId" in value && typeof value.scaffoldId === "string" && "generatedFiles" in value && Array.isArray(value.generatedFiles) && "projectPath" in value && typeof value.projectPath === "string";
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
13
30
|
* UseScaffoldMethod Hook class for Claude Code
|
|
14
31
|
*
|
|
15
32
|
* Provides lifecycle hooks for tool execution:
|
|
@@ -40,6 +57,17 @@ var UseScaffoldMethodHook = class {
|
|
|
40
57
|
decision: __agiflowai_hooks_adapter.DECISION_SKIP,
|
|
41
58
|
message: "File is outside working directory - skipping scaffold method check"
|
|
42
59
|
};
|
|
60
|
+
let fileExists = false;
|
|
61
|
+
try {
|
|
62
|
+
await node_fs_promises.default.access(absoluteFilePath);
|
|
63
|
+
fileExists = true;
|
|
64
|
+
} catch (accessErr) {
|
|
65
|
+
if (!(accessErr instanceof Error && "code" in accessErr && accessErr.code === "ENOENT")) throw accessErr;
|
|
66
|
+
}
|
|
67
|
+
if (fileExists) return {
|
|
68
|
+
decision: __agiflowai_hooks_adapter.DECISION_SKIP,
|
|
69
|
+
message: "File already exists - skipping scaffold method check"
|
|
70
|
+
};
|
|
43
71
|
const executionLog = new __agiflowai_hooks_adapter.ExecutionLogService(context.session_id);
|
|
44
72
|
if (await executionLog.hasExecuted({
|
|
45
73
|
filePath,
|
|
@@ -70,7 +98,12 @@ var UseScaffoldMethodHook = class {
|
|
|
70
98
|
decision: __agiflowai_hooks_adapter.DECISION_SKIP,
|
|
71
99
|
message: "⚠️ Invalid response format from scaffolding methods tool"
|
|
72
100
|
};
|
|
73
|
-
const
|
|
101
|
+
const parsed = JSON.parse(resultText);
|
|
102
|
+
if (!isScaffoldMethodsResponse(parsed)) return {
|
|
103
|
+
decision: __agiflowai_hooks_adapter.DECISION_SKIP,
|
|
104
|
+
message: "⚠️ Unexpected response shape from scaffolding methods tool"
|
|
105
|
+
};
|
|
106
|
+
const data = parsed;
|
|
74
107
|
if (!data.methods || data.methods.length === 0) {
|
|
75
108
|
await executionLog.logExecution({
|
|
76
109
|
filePath,
|
|
@@ -82,19 +115,9 @@ var UseScaffoldMethodHook = class {
|
|
|
82
115
|
message: "No scaffolding methods are available for this project template. You should write new files directly using the Write tool."
|
|
83
116
|
};
|
|
84
117
|
}
|
|
85
|
-
let message = "
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
message += `**${method.name}**\\n`;
|
|
89
|
-
message += `${method.instruction || method.description || "No description available"}\\n`;
|
|
90
|
-
if (method.variables_schema?.required && method.variables_schema.required.length > 0) message += `Required: ${method.variables_schema.required.join(", ")}\\n`;
|
|
91
|
-
message += "\\n";
|
|
92
|
-
}
|
|
93
|
-
if (data.nextCursor) message += `\\n_Note: More methods available. Use cursor "${data.nextCursor}" to see more._\\n\\n`;
|
|
94
|
-
message += "\\n**Instructions:**\\n";
|
|
95
|
-
message += "1. If one of these scaffold methods matches what you need to create, use the `use-scaffold-method` MCP tool instead of writing files manually\\n";
|
|
96
|
-
message += "2. If none of these methods are relevant to your task, proceed to write new files directly using the Write tool\\n";
|
|
97
|
-
message += "3. Using scaffold methods ensures consistency with project patterns and includes all necessary boilerplate\\n";
|
|
118
|
+
let message = "Before writing new files, use `use-scaffold-method` if any of these match your needs:\n\n";
|
|
119
|
+
for (const method of data.methods) message += `- **${method.name}**: ${method.description || "No description available"}\n`;
|
|
120
|
+
if (data.nextCursor) message += `\n_More methods available (cursor: "${data.nextCursor}")._\n`;
|
|
98
121
|
await executionLog.logExecution({
|
|
99
122
|
filePath,
|
|
100
123
|
operation: "list-scaffold-methods",
|
|
@@ -181,7 +204,7 @@ var UseScaffoldMethodHook = class {
|
|
|
181
204
|
};
|
|
182
205
|
}
|
|
183
206
|
if (isScaffoldedFile) {
|
|
184
|
-
const remainingFilesList = remainingFiles.map((f) => ` - ${f}`).join("
|
|
207
|
+
const remainingFilesList = remainingFiles.map((f) => ` - ${f}`).join("\n");
|
|
185
208
|
return {
|
|
186
209
|
decision: __agiflowai_hooks_adapter.DECISION_ALLOW,
|
|
187
210
|
message: `
|
|
@@ -217,7 +240,8 @@ function extractScaffoldId(toolResult) {
|
|
|
217
240
|
if (match) return match[1];
|
|
218
241
|
}
|
|
219
242
|
return null;
|
|
220
|
-
} catch {
|
|
243
|
+
} catch (error) {
|
|
244
|
+
console.error("extractScaffoldId: failed to parse tool result:", error);
|
|
221
245
|
return null;
|
|
222
246
|
}
|
|
223
247
|
}
|
|
@@ -225,28 +249,38 @@ function extractScaffoldId(toolResult) {
|
|
|
225
249
|
* Helper function to get the last scaffold execution for a session
|
|
226
250
|
*/
|
|
227
251
|
async function getLastScaffoldExecution(executionLog) {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
scaffoldId
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
252
|
+
try {
|
|
253
|
+
const entries = await executionLog.loadLog();
|
|
254
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
255
|
+
const entry = entries[i];
|
|
256
|
+
if (entry.operation === "scaffold" && entry.scaffoldId && entry.generatedFiles && entry.generatedFiles.length > 0) return {
|
|
257
|
+
scaffoldId: entry.scaffoldId,
|
|
258
|
+
generatedFiles: entry.generatedFiles,
|
|
259
|
+
featureName: entry.featureName
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
return null;
|
|
263
|
+
} catch (error) {
|
|
264
|
+
console.error("getLastScaffoldExecution: failed to load log:", error);
|
|
265
|
+
return null;
|
|
236
266
|
}
|
|
237
|
-
return null;
|
|
238
267
|
}
|
|
239
268
|
/**
|
|
240
269
|
* Helper function to get list of edited scaffold files
|
|
241
270
|
*/
|
|
242
271
|
async function getEditedScaffoldFiles(executionLog, scaffoldId) {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
const
|
|
247
|
-
|
|
272
|
+
try {
|
|
273
|
+
const entries = await executionLog.loadLog();
|
|
274
|
+
const editedFiles = [];
|
|
275
|
+
for (const entry of entries) if (entry.operation === "scaffold-file-edit" && entry.filePath.startsWith(`scaffold-edit-${scaffoldId}-`)) {
|
|
276
|
+
const filePath = entry.filePath.replace(`scaffold-edit-${scaffoldId}-`, "");
|
|
277
|
+
editedFiles.push(filePath);
|
|
278
|
+
}
|
|
279
|
+
return editedFiles;
|
|
280
|
+
} catch (error) {
|
|
281
|
+
console.error("getEditedScaffoldFiles: failed to load log:", error);
|
|
282
|
+
return [];
|
|
248
283
|
}
|
|
249
|
-
return editedFiles;
|
|
250
284
|
}
|
|
251
285
|
/**
|
|
252
286
|
* Process pending scaffold logs from temp file and copy to ExecutionLogService
|
|
@@ -255,27 +289,33 @@ async function getEditedScaffoldFiles(executionLog, scaffoldId) {
|
|
|
255
289
|
async function processPendingScaffoldLogs(sessionId, scaffoldId) {
|
|
256
290
|
const tempLogFile = node_path.default.join(node_os.default.tmpdir(), `scaffold-mcp-pending-${scaffoldId}.jsonl`);
|
|
257
291
|
try {
|
|
258
|
-
const lines = (await node_fs_promises.default.readFile(tempLogFile, "utf-8")).trim().split("
|
|
292
|
+
const lines = (await node_fs_promises.default.readFile(tempLogFile, "utf-8")).trim().split("\n").filter(Boolean);
|
|
259
293
|
const executionLog = new __agiflowai_hooks_adapter.ExecutionLogService(sessionId);
|
|
260
294
|
try {
|
|
261
295
|
for (const line of lines) try {
|
|
262
|
-
const
|
|
296
|
+
const parsed = JSON.parse(line);
|
|
297
|
+
if (!isPendingScaffoldLogEntry(parsed)) {
|
|
298
|
+
console.error("processPendingScaffoldLogs: skipping malformed entry:", line);
|
|
299
|
+
continue;
|
|
300
|
+
}
|
|
263
301
|
await executionLog.logExecution({
|
|
264
|
-
filePath: `scaffold-${
|
|
302
|
+
filePath: `scaffold-${parsed.scaffoldId}`,
|
|
265
303
|
operation: "scaffold",
|
|
266
304
|
decision: __agiflowai_hooks_adapter.DECISION_ALLOW,
|
|
267
|
-
generatedFiles:
|
|
268
|
-
scaffoldId:
|
|
269
|
-
projectPath:
|
|
270
|
-
featureName:
|
|
305
|
+
generatedFiles: parsed.generatedFiles,
|
|
306
|
+
scaffoldId: parsed.scaffoldId,
|
|
307
|
+
projectPath: parsed.projectPath,
|
|
308
|
+
featureName: parsed.featureName
|
|
271
309
|
});
|
|
272
310
|
} catch (parseError) {
|
|
273
|
-
console.error("
|
|
311
|
+
console.error("processPendingScaffoldLogs: failed to parse line:", parseError);
|
|
274
312
|
}
|
|
275
313
|
} finally {
|
|
276
314
|
try {
|
|
277
315
|
await node_fs_promises.default.unlink(tempLogFile);
|
|
278
|
-
} catch {
|
|
316
|
+
} catch (unlinkError) {
|
|
317
|
+
if (!(unlinkError instanceof Error && "code" in unlinkError && unlinkError.code === "ENOENT")) console.error("processPendingScaffoldLogs: failed to delete temp log file:", unlinkError);
|
|
318
|
+
}
|
|
279
319
|
}
|
|
280
320
|
} catch (error) {
|
|
281
321
|
if (error instanceof Error && "code" in error && error.code !== "ENOENT") console.error("Error processing pending scaffold logs:", error);
|