@stackwright-pro/mcp 0.2.0-alpha.20 → 0.2.0-alpha.21
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/integrity.js +9 -9
- package/dist/integrity.js.map +1 -1
- package/dist/integrity.mjs +9 -9
- package/dist/integrity.mjs.map +1 -1
- package/dist/server.js +33 -313
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +69 -349
- package/dist/server.mjs.map +1 -1
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -1135,7 +1135,6 @@ function setupPackages(opts) {
|
|
|
1135
1135
|
|
|
1136
1136
|
// src/tools/questions.ts
|
|
1137
1137
|
var import_promises = require("fs/promises");
|
|
1138
|
-
var import_node_fs = require("fs");
|
|
1139
1138
|
var import_node_path = require("path");
|
|
1140
1139
|
var import_zod8 = require("zod");
|
|
1141
1140
|
|
|
@@ -1408,12 +1407,12 @@ function registerQuestionTools(server2) {
|
|
|
1408
1407
|
content: [
|
|
1409
1408
|
{
|
|
1410
1409
|
type: "text",
|
|
1411
|
-
text:
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1410
|
+
text: JSON.stringify({
|
|
1411
|
+
phase,
|
|
1412
|
+
skipped: true,
|
|
1413
|
+
reason: "No questions to present (all filtered by dependsOn conditions)",
|
|
1414
|
+
answers: []
|
|
1415
|
+
})
|
|
1417
1416
|
}
|
|
1418
1417
|
],
|
|
1419
1418
|
isError: false
|
|
@@ -1434,144 +1433,6 @@ function registerQuestionTools(server2) {
|
|
|
1434
1433
|
};
|
|
1435
1434
|
}
|
|
1436
1435
|
);
|
|
1437
|
-
server2.tool(
|
|
1438
|
-
"stackwright_pro_get_next_question",
|
|
1439
|
-
"Returns the next unanswered question for a phase as a plain JSON object \u2014 one question at a time. Returns { done: true } when all questions are answered or the phase has no questions. Call this in a loop: present the question in plain chat, get user reply, call record_answer, repeat.",
|
|
1440
|
-
{ phase: import_zod8.z.string().describe('Phase name e.g. "designer", "api", "auth"') },
|
|
1441
|
-
async ({ phase }) => {
|
|
1442
|
-
const SAFE_PHASE = /^[a-z][a-z0-9-]{0,30}$/;
|
|
1443
|
-
if (!SAFE_PHASE.test(phase)) {
|
|
1444
|
-
return {
|
|
1445
|
-
content: [
|
|
1446
|
-
{
|
|
1447
|
-
type: "text",
|
|
1448
|
-
text: JSON.stringify({ error: `Invalid phase name: "${phase.slice(0, 50)}"` })
|
|
1449
|
-
}
|
|
1450
|
-
],
|
|
1451
|
-
isError: true
|
|
1452
|
-
};
|
|
1453
|
-
}
|
|
1454
|
-
const cwd = process.cwd();
|
|
1455
|
-
const questionsPath = (0, import_node_path.join)(cwd, ".stackwright", "questions", `${phase}.json`);
|
|
1456
|
-
let questions = [];
|
|
1457
|
-
try {
|
|
1458
|
-
const raw = await (0, import_promises.readFile)(questionsPath, "utf-8");
|
|
1459
|
-
const parsed = JSON.parse(raw);
|
|
1460
|
-
questions = parsed.questions ?? [];
|
|
1461
|
-
} catch {
|
|
1462
|
-
return { content: [{ type: "text", text: JSON.stringify({ done: true }) }] };
|
|
1463
|
-
}
|
|
1464
|
-
if (questions.length === 0) {
|
|
1465
|
-
return { content: [{ type: "text", text: JSON.stringify({ done: true }) }] };
|
|
1466
|
-
}
|
|
1467
|
-
const answersPath = (0, import_node_path.join)(cwd, ".stackwright", "answers", `${phase}.json`);
|
|
1468
|
-
let answeredIds = /* @__PURE__ */ new Set();
|
|
1469
|
-
try {
|
|
1470
|
-
const raw = await (0, import_promises.readFile)(answersPath, "utf-8");
|
|
1471
|
-
const parsed = JSON.parse(raw);
|
|
1472
|
-
answeredIds = new Set(Object.keys(parsed.answers ?? {}));
|
|
1473
|
-
} catch {
|
|
1474
|
-
}
|
|
1475
|
-
const next = questions.find((q) => !answeredIds.has(q.id));
|
|
1476
|
-
if (!next) {
|
|
1477
|
-
return { content: [{ type: "text", text: JSON.stringify({ done: true }) }] };
|
|
1478
|
-
}
|
|
1479
|
-
return {
|
|
1480
|
-
content: [
|
|
1481
|
-
{
|
|
1482
|
-
type: "text",
|
|
1483
|
-
text: JSON.stringify({
|
|
1484
|
-
done: false,
|
|
1485
|
-
questionId: next.id,
|
|
1486
|
-
question: next.question,
|
|
1487
|
-
type: next.type,
|
|
1488
|
-
options: next.options ?? null,
|
|
1489
|
-
help: next.help ?? null,
|
|
1490
|
-
index: questions.indexOf(next) + 1,
|
|
1491
|
-
total: questions.length
|
|
1492
|
-
})
|
|
1493
|
-
}
|
|
1494
|
-
]
|
|
1495
|
-
};
|
|
1496
|
-
}
|
|
1497
|
-
);
|
|
1498
|
-
server2.tool(
|
|
1499
|
-
"stackwright_pro_record_answer",
|
|
1500
|
-
"Records a single answer to a phase question. Appends to .stackwright/answers/{phase}.json incrementally. Idempotent \u2014 calling twice for the same questionId overwrites. Call after receiving each user reply in the conversational question loop.",
|
|
1501
|
-
{
|
|
1502
|
-
phase: import_zod8.z.string().describe('Phase name e.g. "designer"'),
|
|
1503
|
-
questionId: import_zod8.z.string().describe('The question ID from get_next_question, e.g. "designer-1"'),
|
|
1504
|
-
answer: import_zod8.z.string().describe("The user's free-text answer")
|
|
1505
|
-
},
|
|
1506
|
-
async ({ phase, questionId, answer }) => {
|
|
1507
|
-
const SAFE_PHASE = /^[a-z][a-z0-9-]{0,30}$/;
|
|
1508
|
-
if (!SAFE_PHASE.test(phase)) {
|
|
1509
|
-
return {
|
|
1510
|
-
content: [
|
|
1511
|
-
{ type: "text", text: JSON.stringify({ error: "Invalid phase name" }) }
|
|
1512
|
-
],
|
|
1513
|
-
isError: true
|
|
1514
|
-
};
|
|
1515
|
-
}
|
|
1516
|
-
if (!/^[a-z0-9][a-z0-9-]{0,63}$/i.test(questionId)) {
|
|
1517
|
-
return {
|
|
1518
|
-
content: [
|
|
1519
|
-
{ type: "text", text: JSON.stringify({ error: "Invalid questionId" }) }
|
|
1520
|
-
],
|
|
1521
|
-
isError: true
|
|
1522
|
-
};
|
|
1523
|
-
}
|
|
1524
|
-
const safeAnswer = answer.slice(0, 2e3);
|
|
1525
|
-
const cwd = process.cwd();
|
|
1526
|
-
const answersDir = (0, import_node_path.join)(cwd, ".stackwright", "answers");
|
|
1527
|
-
const answersPath = (0, import_node_path.join)(answersDir, `${phase}.json`);
|
|
1528
|
-
if ((0, import_node_fs.existsSync)(answersDir) && (0, import_node_fs.lstatSync)(answersDir).isSymbolicLink()) {
|
|
1529
|
-
return {
|
|
1530
|
-
content: [
|
|
1531
|
-
{
|
|
1532
|
-
type: "text",
|
|
1533
|
-
text: JSON.stringify({ error: "answers dir is a symlink \u2014 refusing to write" })
|
|
1534
|
-
}
|
|
1535
|
-
],
|
|
1536
|
-
isError: true
|
|
1537
|
-
};
|
|
1538
|
-
}
|
|
1539
|
-
(0, import_node_fs.mkdirSync)(answersDir, { recursive: true });
|
|
1540
|
-
let existing = {
|
|
1541
|
-
version: "1.0",
|
|
1542
|
-
phase,
|
|
1543
|
-
answers: {}
|
|
1544
|
-
};
|
|
1545
|
-
try {
|
|
1546
|
-
if ((0, import_node_fs.existsSync)(answersPath)) {
|
|
1547
|
-
if ((0, import_node_fs.lstatSync)(answersPath).isSymbolicLink()) {
|
|
1548
|
-
return {
|
|
1549
|
-
content: [
|
|
1550
|
-
{
|
|
1551
|
-
type: "text",
|
|
1552
|
-
text: JSON.stringify({ error: "answers file is a symlink \u2014 refusing to write" })
|
|
1553
|
-
}
|
|
1554
|
-
],
|
|
1555
|
-
isError: true
|
|
1556
|
-
};
|
|
1557
|
-
}
|
|
1558
|
-
const raw = await (0, import_promises.readFile)(answersPath, "utf-8");
|
|
1559
|
-
existing = JSON.parse(raw);
|
|
1560
|
-
}
|
|
1561
|
-
} catch {
|
|
1562
|
-
}
|
|
1563
|
-
existing.answers[questionId] = safeAnswer;
|
|
1564
|
-
existing.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1565
|
-
const tmp = `${answersPath}.tmp`;
|
|
1566
|
-
await (0, import_promises.writeFile)(tmp, JSON.stringify(existing, null, 2), "utf-8");
|
|
1567
|
-
(0, import_node_fs.renameSync)(tmp, answersPath);
|
|
1568
|
-
return {
|
|
1569
|
-
content: [
|
|
1570
|
-
{ type: "text", text: JSON.stringify({ recorded: true, phase, questionId }) }
|
|
1571
|
-
]
|
|
1572
|
-
};
|
|
1573
|
-
}
|
|
1574
|
-
);
|
|
1575
1436
|
}
|
|
1576
1437
|
|
|
1577
1438
|
// src/tools/orchestration.ts
|
|
@@ -1743,57 +1604,7 @@ function handleGetOtterName(input) {
|
|
|
1743
1604
|
isError: false
|
|
1744
1605
|
};
|
|
1745
1606
|
}
|
|
1746
|
-
function handleSaveBuildContext(input) {
|
|
1747
|
-
const cwd = input._cwd ?? process.cwd();
|
|
1748
|
-
const dir = (0, import_path3.join)(cwd, ".stackwright");
|
|
1749
|
-
const filePath = (0, import_path3.join)(dir, "build-context.json");
|
|
1750
|
-
try {
|
|
1751
|
-
(0, import_fs3.mkdirSync)(dir, { recursive: true });
|
|
1752
|
-
if ((0, import_fs3.existsSync)(filePath)) {
|
|
1753
|
-
const stat = (0, import_fs3.lstatSync)(filePath);
|
|
1754
|
-
if (stat.isSymbolicLink()) {
|
|
1755
|
-
return {
|
|
1756
|
-
text: JSON.stringify({
|
|
1757
|
-
success: false,
|
|
1758
|
-
error: `Refusing to write to symlink: ${filePath}`
|
|
1759
|
-
}),
|
|
1760
|
-
isError: true
|
|
1761
|
-
};
|
|
1762
|
-
}
|
|
1763
|
-
}
|
|
1764
|
-
const payload = {
|
|
1765
|
-
version: "1.0",
|
|
1766
|
-
savedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1767
|
-
buildContext: input.buildContext
|
|
1768
|
-
};
|
|
1769
|
-
(0, import_fs3.writeFileSync)(filePath, JSON.stringify(payload, null, 2) + "\n");
|
|
1770
|
-
return {
|
|
1771
|
-
text: JSON.stringify({ success: true, path: filePath }),
|
|
1772
|
-
isError: false
|
|
1773
|
-
};
|
|
1774
|
-
} catch (err) {
|
|
1775
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
1776
|
-
return {
|
|
1777
|
-
text: JSON.stringify({ success: false, error: message }),
|
|
1778
|
-
isError: true
|
|
1779
|
-
};
|
|
1780
|
-
}
|
|
1781
|
-
}
|
|
1782
1607
|
function registerOrchestrationTools(server2) {
|
|
1783
|
-
server2.tool(
|
|
1784
|
-
"stackwright_pro_save_build_context",
|
|
1785
|
-
`Save the user's initial build description to .stackwright/build-context.json. Call this once at startup after the user answers the opening "what are you building" question. The saved context is automatically prepended to specialist prompts by stackwright_pro_build_specialist_prompt.`,
|
|
1786
|
-
{
|
|
1787
|
-
buildContext: import_zod9.z.string().describe("Free-text description of what the user wants to build")
|
|
1788
|
-
},
|
|
1789
|
-
async ({ buildContext }) => {
|
|
1790
|
-
const { text, isError } = handleSaveBuildContext({ buildContext });
|
|
1791
|
-
return {
|
|
1792
|
-
content: [{ type: "text", text }],
|
|
1793
|
-
isError
|
|
1794
|
-
};
|
|
1795
|
-
}
|
|
1796
|
-
);
|
|
1797
1608
|
server2.tool(
|
|
1798
1609
|
"stackwright_pro_parse_otter_response",
|
|
1799
1610
|
"Parse and validate a specialist otter's QUESTION_COLLECTION_MODE JSON response. Handles JSON extraction from LLM responses (strips markdown, fixes single quotes, trailing commas). Detects the phase from the otter name. Use this immediately after invoke_agent() to get a validated manifest phase object.",
|
|
@@ -2072,62 +1883,28 @@ function handleSetPipelineState(input) {
|
|
|
2072
1883
|
return { text: JSON.stringify({ error: true, message: String(err) }), isError: true };
|
|
2073
1884
|
}
|
|
2074
1885
|
}
|
|
2075
|
-
function handleCheckExecutionReady(_cwd
|
|
1886
|
+
function handleCheckExecutionReady(_cwd) {
|
|
2076
1887
|
const cwd = _cwd ?? process.cwd();
|
|
2077
|
-
if (phase) {
|
|
2078
|
-
if (!isValidPhase(phase)) {
|
|
2079
|
-
return {
|
|
2080
|
-
text: JSON.stringify({
|
|
2081
|
-
error: true,
|
|
2082
|
-
message: `Invalid phase: ${phase}. Valid phases are: ${PHASE_ORDER.join(", ")}`
|
|
2083
|
-
}),
|
|
2084
|
-
isError: true
|
|
2085
|
-
};
|
|
2086
|
-
}
|
|
2087
|
-
const answerFile = (0, import_path4.join)(cwd, ".stackwright", "answers", `${phase}.json`);
|
|
2088
|
-
if (!(0, import_fs4.existsSync)(answerFile)) {
|
|
2089
|
-
return {
|
|
2090
|
-
text: JSON.stringify({ ready: false, phase, reason: "Answer file not found" }),
|
|
2091
|
-
isError: false
|
|
2092
|
-
};
|
|
2093
|
-
}
|
|
2094
|
-
try {
|
|
2095
|
-
const raw = safeReadSync(answerFile);
|
|
2096
|
-
const parsed = JSON.parse(raw);
|
|
2097
|
-
if (typeof parsed["version"] !== "string" || typeof parsed["phase"] !== "string" || typeof parsed["answers"] !== "object" || parsed["answers"] === null) {
|
|
2098
|
-
return {
|
|
2099
|
-
text: JSON.stringify({ ready: false, phase, reason: "Answer file is malformed" }),
|
|
2100
|
-
isError: false
|
|
2101
|
-
};
|
|
2102
|
-
}
|
|
2103
|
-
return { text: JSON.stringify({ ready: true, phase }), isError: false };
|
|
2104
|
-
} catch {
|
|
2105
|
-
return {
|
|
2106
|
-
text: JSON.stringify({ ready: false, phase, reason: "Answer file could not be parsed" }),
|
|
2107
|
-
isError: false
|
|
2108
|
-
};
|
|
2109
|
-
}
|
|
2110
|
-
}
|
|
2111
1888
|
try {
|
|
2112
1889
|
const answersDir = (0, import_path4.join)(cwd, ".stackwright", "answers");
|
|
2113
1890
|
const answeredPhases = [];
|
|
2114
1891
|
const missingPhases = [];
|
|
2115
|
-
for (const
|
|
2116
|
-
const answerFile = (0, import_path4.join)(answersDir, `${
|
|
1892
|
+
for (const phase of PHASE_ORDER) {
|
|
1893
|
+
const answerFile = (0, import_path4.join)(answersDir, `${phase}.json`);
|
|
2117
1894
|
if ((0, import_fs4.existsSync)(answerFile)) {
|
|
2118
1895
|
try {
|
|
2119
1896
|
const raw = safeReadSync(answerFile);
|
|
2120
1897
|
const parsed = JSON.parse(raw);
|
|
2121
1898
|
if (typeof parsed["version"] !== "string" || typeof parsed["phase"] !== "string" || typeof parsed["answers"] !== "object" || parsed["answers"] === null) {
|
|
2122
|
-
missingPhases.push(
|
|
1899
|
+
missingPhases.push(phase);
|
|
2123
1900
|
continue;
|
|
2124
1901
|
}
|
|
2125
|
-
answeredPhases.push(
|
|
1902
|
+
answeredPhases.push(phase);
|
|
2126
1903
|
} catch {
|
|
2127
|
-
missingPhases.push(
|
|
1904
|
+
missingPhases.push(phase);
|
|
2128
1905
|
}
|
|
2129
1906
|
} else {
|
|
2130
|
-
missingPhases.push(
|
|
1907
|
+
missingPhases.push(phase);
|
|
2131
1908
|
}
|
|
2132
1909
|
}
|
|
2133
1910
|
return {
|
|
@@ -2237,17 +2014,6 @@ function handleBuildSpecialistPrompt(input) {
|
|
|
2237
2014
|
if ((0, import_fs4.existsSync)(answersPath)) {
|
|
2238
2015
|
answers = JSON.parse(safeReadSync(answersPath));
|
|
2239
2016
|
}
|
|
2240
|
-
let buildContextText = "";
|
|
2241
|
-
const buildContextPath = (0, import_path4.join)(cwd, ".stackwright", "build-context.json");
|
|
2242
|
-
if ((0, import_fs4.existsSync)(buildContextPath)) {
|
|
2243
|
-
try {
|
|
2244
|
-
const bcRaw = JSON.parse(safeReadSync(buildContextPath));
|
|
2245
|
-
if (typeof bcRaw.buildContext === "string" && bcRaw.buildContext.trim().length > 0) {
|
|
2246
|
-
buildContextText = bcRaw.buildContext.trim();
|
|
2247
|
-
}
|
|
2248
|
-
} catch {
|
|
2249
|
-
}
|
|
2250
|
-
}
|
|
2251
2017
|
const deps = PHASE_DEPENDENCIES[phase];
|
|
2252
2018
|
const artifactSections = [];
|
|
2253
2019
|
const missingDependencies = [];
|
|
@@ -2258,14 +2024,13 @@ function handleBuildSpecialistPrompt(input) {
|
|
|
2258
2024
|
const content = JSON.parse(safeReadSync(artifactPath));
|
|
2259
2025
|
const expectedOtter = PHASE_TO_OTTER2[dep];
|
|
2260
2026
|
const artifactOtter = content["generatedBy"];
|
|
2261
|
-
const normalizedOtter = artifactOtter?.replace(/-[a-f0-9]{6}$/, "");
|
|
2262
2027
|
if (!artifactOtter) {
|
|
2263
2028
|
missingDependencies.push(dep);
|
|
2264
2029
|
artifactSections.push(
|
|
2265
2030
|
`[${artifactFile}]:
|
|
2266
2031
|
(integrity check failed: missing generatedBy field)`
|
|
2267
2032
|
);
|
|
2268
|
-
} else if (
|
|
2033
|
+
} else if (artifactOtter !== expectedOtter) {
|
|
2269
2034
|
missingDependencies.push(dep);
|
|
2270
2035
|
artifactSections.push(
|
|
2271
2036
|
`[${artifactFile}]:
|
|
@@ -2281,11 +2046,7 @@ ${JSON.stringify(content, null, 2)}`);
|
|
|
2281
2046
|
(not yet available)`);
|
|
2282
2047
|
}
|
|
2283
2048
|
}
|
|
2284
|
-
const parts = [];
|
|
2285
|
-
if (buildContextText) {
|
|
2286
|
-
parts.push("BUILD_CONTEXT:", buildContextText, "");
|
|
2287
|
-
}
|
|
2288
|
-
parts.push("ANSWERS:", JSON.stringify(answers, null, 2));
|
|
2049
|
+
const parts = ["ANSWERS:", JSON.stringify(answers, null, 2)];
|
|
2289
2050
|
if (artifactSections.length > 0) {
|
|
2290
2051
|
parts.push("", "UPSTREAM ARTIFACTS:", "", ...artifactSections);
|
|
2291
2052
|
}
|
|
@@ -2444,11 +2205,9 @@ function registerPipelineTools(server2) {
|
|
|
2444
2205
|
);
|
|
2445
2206
|
server2.tool(
|
|
2446
2207
|
"stackwright_pro_check_execution_ready",
|
|
2447
|
-
`Check all phases have answer files in .stackwright/answers/.
|
|
2448
|
-
{
|
|
2449
|
-
|
|
2450
|
-
},
|
|
2451
|
-
async ({ phase }) => res(handleCheckExecutionReady(void 0, phase))
|
|
2208
|
+
`Check all phases have answer files in .stackwright/answers/. ${DESC}`,
|
|
2209
|
+
{},
|
|
2210
|
+
async () => res(handleCheckExecutionReady())
|
|
2452
2211
|
);
|
|
2453
2212
|
server2.tool(
|
|
2454
2213
|
"stackwright_pro_list_artifacts",
|
|
@@ -2458,49 +2217,12 @@ function registerPipelineTools(server2) {
|
|
|
2458
2217
|
);
|
|
2459
2218
|
server2.tool(
|
|
2460
2219
|
"stackwright_pro_write_phase_questions",
|
|
2461
|
-
`Parse otter question-collection response \u2192 .stackwright/questions/{phase}.json.
|
|
2220
|
+
`Parse otter question-collection response \u2192 .stackwright/questions/{phase}.json. ${DESC}`,
|
|
2462
2221
|
{
|
|
2463
|
-
phase: import_zod10.z.string().
|
|
2464
|
-
responseText: import_zod10.z.string().
|
|
2465
|
-
questions: jsonCoerce(import_zod10.z.array(import_zod10.z.any()).optional()).describe(
|
|
2466
|
-
"Questions array for direct specialist write"
|
|
2467
|
-
)
|
|
2222
|
+
phase: import_zod10.z.string().describe('Phase name, e.g. "designer"'),
|
|
2223
|
+
responseText: import_zod10.z.string().describe("Raw LLM response from QUESTION_COLLECTION_MODE")
|
|
2468
2224
|
},
|
|
2469
|
-
async ({ phase, responseText
|
|
2470
|
-
if (phase && questions && Array.isArray(questions)) {
|
|
2471
|
-
const SAFE_PHASE = /^[a-z][a-z0-9-]{0,30}$/;
|
|
2472
|
-
if (!SAFE_PHASE.test(phase)) {
|
|
2473
|
-
return {
|
|
2474
|
-
content: [
|
|
2475
|
-
{ type: "text", text: JSON.stringify({ error: `Invalid phase name` }) }
|
|
2476
|
-
],
|
|
2477
|
-
isError: true
|
|
2478
|
-
};
|
|
2479
|
-
}
|
|
2480
|
-
const questionsDir = (0, import_path4.join)(process.cwd(), ".stackwright", "questions");
|
|
2481
|
-
(0, import_fs4.mkdirSync)(questionsDir, { recursive: true });
|
|
2482
|
-
const outPath = (0, import_path4.join)(questionsDir, `${phase}.json`);
|
|
2483
|
-
(0, import_fs4.writeFileSync)(
|
|
2484
|
-
outPath,
|
|
2485
|
-
JSON.stringify({ phase, questions, writtenAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2)
|
|
2486
|
-
);
|
|
2487
|
-
return {
|
|
2488
|
-
content: [
|
|
2489
|
-
{
|
|
2490
|
-
type: "text",
|
|
2491
|
-
text: JSON.stringify({
|
|
2492
|
-
written: true,
|
|
2493
|
-
phase,
|
|
2494
|
-
count: questions.length
|
|
2495
|
-
})
|
|
2496
|
-
}
|
|
2497
|
-
]
|
|
2498
|
-
};
|
|
2499
|
-
}
|
|
2500
|
-
return res(
|
|
2501
|
-
handleWritePhaseQuestions({ phase: phase ?? "", responseText: responseText ?? "" })
|
|
2502
|
-
);
|
|
2503
|
-
}
|
|
2225
|
+
async ({ phase, responseText }) => res(handleWritePhaseQuestions({ phase, responseText }))
|
|
2504
2226
|
);
|
|
2505
2227
|
server2.tool(
|
|
2506
2228
|
"stackwright_pro_build_specialist_prompt",
|
|
@@ -2755,9 +2477,7 @@ function registerSafeWriteTools(server2) {
|
|
|
2755
2477
|
callerOtter: import_zod11.z.string().describe('The otter agent name requesting the write, e.g. "stackwright-pro-page-otter"'),
|
|
2756
2478
|
filePath: import_zod11.z.string().describe('Relative path from project root, e.g. "pages/dashboard/content.yml"'),
|
|
2757
2479
|
content: import_zod11.z.string().describe("File content to write"),
|
|
2758
|
-
createDirectories:
|
|
2759
|
-
"Create parent directories if they don't exist. Default: true"
|
|
2760
|
-
)
|
|
2480
|
+
createDirectories: import_zod11.z.boolean().optional().describe("Create parent directories if they don't exist. Default: true")
|
|
2761
2481
|
},
|
|
2762
2482
|
async ({ callerOtter, filePath, content, createDirectories }) => {
|
|
2763
2483
|
const result = handleSafeWrite({
|
|
@@ -3171,39 +2891,39 @@ var import_path7 = require("path");
|
|
|
3171
2891
|
var _checksums = /* @__PURE__ */ new Map([
|
|
3172
2892
|
[
|
|
3173
2893
|
"stackwright-pro-api-otter.json",
|
|
3174
|
-
"
|
|
2894
|
+
"f1cc9edf2dd1df3ebcea1d0ab33d17a358faaf8aa97ee232cd7994042f2eac0d"
|
|
3175
2895
|
],
|
|
3176
2896
|
[
|
|
3177
2897
|
"stackwright-pro-auth-otter.json",
|
|
3178
|
-
"
|
|
2898
|
+
"a19e06c503209a8a35fe321d30448623545b36b48c47a6ec064d13406ad1f725"
|
|
3179
2899
|
],
|
|
3180
2900
|
[
|
|
3181
2901
|
"stackwright-pro-dashboard-otter.json",
|
|
3182
|
-
"
|
|
2902
|
+
"b3cb3d7554f2e9eed3b57d5e0e3bf85d6ba5b4db5d3af5514391cf0575fcc001"
|
|
3183
2903
|
],
|
|
3184
2904
|
[
|
|
3185
2905
|
"stackwright-pro-data-otter.json",
|
|
3186
|
-
"
|
|
2906
|
+
"bfacb87ae82867472a75982215554336a105a658d6cd3dd2c8b819fa1e11d7ac"
|
|
3187
2907
|
],
|
|
3188
2908
|
[
|
|
3189
2909
|
"stackwright-pro-designer-otter.json",
|
|
3190
|
-
"
|
|
2910
|
+
"c58fa7c7ead9e6398074e1c7ce3f31a8ef4eb3679f5fa18cc03cae3a87878c88"
|
|
3191
2911
|
],
|
|
3192
2912
|
[
|
|
3193
2913
|
"stackwright-pro-foreman-otter.json",
|
|
3194
|
-
"
|
|
2914
|
+
"f52264c1f6297b72f3da6d92d41b6d63356db776242caeab25571e6a8df628e4"
|
|
3195
2915
|
],
|
|
3196
2916
|
[
|
|
3197
2917
|
"stackwright-pro-page-otter.json",
|
|
3198
|
-
"
|
|
2918
|
+
"65bec3a3a0dda6b7591bba2de9399f1e3a4fb99cfe1075342f4f4be98d917b67"
|
|
3199
2919
|
],
|
|
3200
2920
|
[
|
|
3201
2921
|
"stackwright-pro-theme-otter.json",
|
|
3202
|
-
"
|
|
2922
|
+
"1f182326f1acd3d4091a38c7012085cbb4945893e95be4ca3de72318ad092767"
|
|
3203
2923
|
],
|
|
3204
2924
|
[
|
|
3205
2925
|
"stackwright-pro-workflow-otter.json",
|
|
3206
|
-
"
|
|
2926
|
+
"0eec9d6a731678cf547c2a7b0b6fc338ca143c35501365a1e4e5dd2779dd5510"
|
|
3207
2927
|
]
|
|
3208
2928
|
]);
|
|
3209
2929
|
Object.freeze(_checksums);
|
|
@@ -3809,7 +3529,7 @@ var package_default = {
|
|
|
3809
3529
|
"test:coverage": "vitest run --coverage"
|
|
3810
3530
|
},
|
|
3811
3531
|
name: "@stackwright-pro/mcp",
|
|
3812
|
-
version: "0.2.0-alpha.
|
|
3532
|
+
version: "0.2.0-alpha.13",
|
|
3813
3533
|
description: "MCP tools for Stackwright Pro - Data Explorer, Security, ISR, and Dashboard generation",
|
|
3814
3534
|
license: "PROPRIETARY",
|
|
3815
3535
|
main: "./dist/server.js",
|