@doquflow/cli 1.7.0 → 2.0.0
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/commands/doctor.js +270 -0
- package/dist/commands/help.js +1 -0
- package/dist/commands/ingest.js +6 -3
- package/dist/commands/init.js +3 -3
- package/dist/commands/query.js +6 -3
- package/dist/commands/rewiki.js +6 -3
- package/dist/commands/sync.js +10 -5
- package/dist/commands/ui.js +1 -1
- package/dist/commands/update.js +1 -1
- package/dist/commands/watch.js +8 -5
- package/dist/index.js +7 -0
- package/package.json +4 -3
- package/ui-dist/assets/index-BMnRdqwa.js +44 -0
- package/ui-dist/index.html +1 -1
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* docuflow doctor
|
|
4
|
+
*
|
|
5
|
+
* Diagnostic command that reports installed DocuFlow packages, MCP server
|
|
6
|
+
* registrations, detected workflow, and actionable recommendations.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* docuflow doctor # human-readable report
|
|
10
|
+
* docuflow doctor --json # machine-readable JSON
|
|
11
|
+
* docuflow doctor --quiet # recommendations only
|
|
12
|
+
*/
|
|
13
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.run = run;
|
|
18
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
19
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
20
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
21
|
+
// ── Package version resolution ────────────────────────────────────────────────
|
|
22
|
+
function resolvePackageVersion(pkgName) {
|
|
23
|
+
const candidates = [
|
|
24
|
+
() => require.resolve(`${pkgName}/package.json`),
|
|
25
|
+
() => node_path_1.default.resolve(__dirname, "../../../", pkgName.replace("@doquflow/", ""), "package.json"),
|
|
26
|
+
() => node_path_1.default.resolve(__dirname, "../../", pkgName.replace("@doquflow/", ""), "package.json"),
|
|
27
|
+
];
|
|
28
|
+
for (const c of candidates) {
|
|
29
|
+
try {
|
|
30
|
+
const pkgPath = c();
|
|
31
|
+
const raw = node_fs_1.default.readFileSync(pkgPath, "utf8");
|
|
32
|
+
return JSON.parse(raw).version;
|
|
33
|
+
}
|
|
34
|
+
catch { /* try next */ }
|
|
35
|
+
}
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
function getInstalledPackages() {
|
|
39
|
+
const packages = ["@doquflow/cli", "@doquflow/core", "@doquflow/studio", "@doquflow/server"];
|
|
40
|
+
return packages.map(name => ({ name, version: resolvePackageVersion(name) }));
|
|
41
|
+
}
|
|
42
|
+
function getClaudeDesktopConfigPath() {
|
|
43
|
+
const p = process.platform;
|
|
44
|
+
if (p === "darwin")
|
|
45
|
+
return node_path_1.default.join(node_os_1.default.homedir(), "Library", "Application Support", "Claude", "claude_desktop_config.json");
|
|
46
|
+
if (p === "win32")
|
|
47
|
+
return node_path_1.default.join(node_os_1.default.homedir(), "AppData", "Roaming", "Claude", "claude_desktop_config.json");
|
|
48
|
+
return node_path_1.default.join(node_os_1.default.homedir(), ".config", "Claude", "claude_desktop_config.json");
|
|
49
|
+
}
|
|
50
|
+
function getMcpRegistrations(projectPath) {
|
|
51
|
+
const results = [];
|
|
52
|
+
// Project-level .mcp.json
|
|
53
|
+
const projectMcp = node_path_1.default.join(projectPath, ".mcp.json");
|
|
54
|
+
try {
|
|
55
|
+
const cfg = JSON.parse(node_fs_1.default.readFileSync(projectMcp, "utf8"));
|
|
56
|
+
const entry = cfg.mcpServers?.docuflow;
|
|
57
|
+
results.push({ source: ".mcp.json", registered: !!entry, command: entry?.command, args: entry?.args });
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
results.push({ source: ".mcp.json", registered: false });
|
|
61
|
+
}
|
|
62
|
+
// Claude Desktop
|
|
63
|
+
try {
|
|
64
|
+
const cfg = JSON.parse(node_fs_1.default.readFileSync(getClaudeDesktopConfigPath(), "utf8"));
|
|
65
|
+
const entry = cfg.mcpServers?.docuflow;
|
|
66
|
+
results.push({ source: "Claude Desktop", registered: !!entry, command: entry?.command, args: entry?.args });
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
results.push({ source: "Claude Desktop", registered: false });
|
|
70
|
+
}
|
|
71
|
+
// VS Code user MCP
|
|
72
|
+
const vscodePath = process.platform === "darwin"
|
|
73
|
+
? node_path_1.default.join(node_os_1.default.homedir(), "Library", "Application Support", "Code", "User", "mcp.json")
|
|
74
|
+
: process.platform === "win32"
|
|
75
|
+
? node_path_1.default.join(node_os_1.default.homedir(), "AppData", "Roaming", "Code", "User", "mcp.json")
|
|
76
|
+
: node_path_1.default.join(node_os_1.default.homedir(), ".config", "Code", "User", "mcp.json");
|
|
77
|
+
try {
|
|
78
|
+
const cfg = JSON.parse(node_fs_1.default.readFileSync(vscodePath, "utf8"));
|
|
79
|
+
const entry = cfg.servers?.docuflow;
|
|
80
|
+
results.push({ source: "VS Code (user)", registered: !!entry, command: entry?.command, args: entry?.args });
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
results.push({ source: "VS Code (user)", registered: false });
|
|
84
|
+
}
|
|
85
|
+
// Copilot CLI
|
|
86
|
+
const copilotPath = node_path_1.default.join(node_os_1.default.homedir(), ".copilot", "mcp-config.json");
|
|
87
|
+
try {
|
|
88
|
+
const cfg = JSON.parse(node_fs_1.default.readFileSync(copilotPath, "utf8"));
|
|
89
|
+
const entry = cfg.mcpServers?.docuflow;
|
|
90
|
+
results.push({ source: "Copilot CLI", registered: !!entry, command: entry?.command, args: entry?.args });
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
results.push({ source: "Copilot CLI", registered: false });
|
|
94
|
+
}
|
|
95
|
+
return results;
|
|
96
|
+
}
|
|
97
|
+
function detectWorkflow(projectPath) {
|
|
98
|
+
const docuDir = node_path_1.default.join(projectPath, ".docuflow");
|
|
99
|
+
const hasDocuflow = node_fs_1.default.existsSync(docuDir);
|
|
100
|
+
let hasSources = false;
|
|
101
|
+
let hasSpecs = false;
|
|
102
|
+
let hasQueryUsage = false;
|
|
103
|
+
let watchRunning = false;
|
|
104
|
+
if (hasDocuflow) {
|
|
105
|
+
try {
|
|
106
|
+
hasSources = node_fs_1.default.readdirSync(node_path_1.default.join(docuDir, "sources")).some(f => f.endsWith(".md"));
|
|
107
|
+
}
|
|
108
|
+
catch { /* */ }
|
|
109
|
+
try {
|
|
110
|
+
hasSpecs = node_fs_1.default.readdirSync(node_path_1.default.join(docuDir, "specs")).some(f => f.endsWith(".md"));
|
|
111
|
+
}
|
|
112
|
+
catch { /* */ }
|
|
113
|
+
try {
|
|
114
|
+
const log = node_fs_1.default.readFileSync(node_path_1.default.join(docuDir, "log.md"), "utf8");
|
|
115
|
+
hasQueryUsage = /query-wiki|queryWiki/i.test(log);
|
|
116
|
+
}
|
|
117
|
+
catch { /* */ }
|
|
118
|
+
// Check watch daemon PID file
|
|
119
|
+
const pidFile = node_path_1.default.join(docuDir, "watch.pid.json");
|
|
120
|
+
try {
|
|
121
|
+
const data = JSON.parse(node_fs_1.default.readFileSync(pidFile, "utf8"));
|
|
122
|
+
try {
|
|
123
|
+
process.kill(data.pid, 0);
|
|
124
|
+
watchRunning = true;
|
|
125
|
+
}
|
|
126
|
+
catch { /* not running */ }
|
|
127
|
+
}
|
|
128
|
+
catch { /* no pid file */ }
|
|
129
|
+
}
|
|
130
|
+
return { hasDocuflow, hasSources, hasSpecs, hasQueryUsage, watchRunning };
|
|
131
|
+
}
|
|
132
|
+
function getHealthSummary(projectPath) {
|
|
133
|
+
const docuDir = node_path_1.default.join(projectPath, ".docuflow");
|
|
134
|
+
const byCategory = { entities: 0, concepts: 0, timelines: 0, syntheses: 0 };
|
|
135
|
+
for (const cat of Object.keys(byCategory)) {
|
|
136
|
+
try {
|
|
137
|
+
const files = node_fs_1.default.readdirSync(node_path_1.default.join(docuDir, "wiki", cat));
|
|
138
|
+
byCategory[cat] = files.filter(f => f.endsWith(".md")).length;
|
|
139
|
+
}
|
|
140
|
+
catch { /* dir may not exist */ }
|
|
141
|
+
}
|
|
142
|
+
const totalPages = Object.values(byCategory).reduce((a, b) => a + b, 0);
|
|
143
|
+
let lastUpdate = "never";
|
|
144
|
+
try {
|
|
145
|
+
const log = node_fs_1.default.readFileSync(node_path_1.default.join(docuDir, "log.md"), "utf8");
|
|
146
|
+
const match = log.match(/\[(\d{4}-\d{2}-\d{2}[^\]]*)\]/);
|
|
147
|
+
if (match) {
|
|
148
|
+
const d = new Date(match[1]);
|
|
149
|
+
if (!isNaN(d.getTime())) {
|
|
150
|
+
const diffH = Math.floor((Date.now() - d.getTime()) / 3_600_000);
|
|
151
|
+
lastUpdate = diffH < 1 ? "just now" : diffH < 24 ? `${diffH}h ago` : `${Math.floor(diffH / 24)}d ago`;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
catch { /* */ }
|
|
156
|
+
return { totalPages, byCategory, lastUpdate, healthScore: null };
|
|
157
|
+
}
|
|
158
|
+
function buildRecommendations(packages, registrations, workflow, health) {
|
|
159
|
+
const recs = [];
|
|
160
|
+
const pkgMap = Object.fromEntries(packages.map(p => [p.name, p.version]));
|
|
161
|
+
// Core/Studio installed?
|
|
162
|
+
if (!pkgMap["@doquflow/core"] && !pkgMap["@doquflow/studio"]) {
|
|
163
|
+
if (pkgMap["@doquflow/cli"]) {
|
|
164
|
+
// CLI installs core+studio transitively — this just means they weren't directly required
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
recs.push({ severity: "error", message: "No DocuFlow packages detected", action: 'Run: npm i -g @doquflow/cli' });
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
// Suggest minimal install if only using query/ingest
|
|
171
|
+
const hasCli = !!pkgMap["@doquflow/cli"];
|
|
172
|
+
const hasCore = !!pkgMap["@doquflow/core"];
|
|
173
|
+
const hasStudio = !!pkgMap["@doquflow/studio"];
|
|
174
|
+
if (hasCli && !workflow.watchRunning && !workflow.hasQueryUsage && hasCore && !hasStudio) {
|
|
175
|
+
recs.push({ severity: "info", message: "You only use core tools (query/ingest)", action: "Consider: npm i -g @doquflow/core for a smaller install" });
|
|
176
|
+
}
|
|
177
|
+
// Not initialised
|
|
178
|
+
if (!workflow.hasDocuflow) {
|
|
179
|
+
recs.push({ severity: "error", message: ".docuflow/ not found in this directory", action: "Run: docuflow init" });
|
|
180
|
+
return recs; // no point checking further
|
|
181
|
+
}
|
|
182
|
+
// No MCP registration anywhere
|
|
183
|
+
const anyRegistered = registrations.some(r => r.registered);
|
|
184
|
+
if (!anyRegistered) {
|
|
185
|
+
recs.push({ severity: "error", message: "DocuFlow is not registered with any MCP host", action: "Run: docuflow init (re-run is safe)" });
|
|
186
|
+
}
|
|
187
|
+
// No sources
|
|
188
|
+
if (!workflow.hasSources) {
|
|
189
|
+
recs.push({ severity: "warn", message: "No source documents in .docuflow/sources/", action: "Drop a markdown file there, then run: docuflow ingest" });
|
|
190
|
+
}
|
|
191
|
+
// Empty wiki
|
|
192
|
+
if (health.totalPages === 0 && workflow.hasSources) {
|
|
193
|
+
recs.push({ severity: "warn", message: "Wiki is empty but sources exist", action: "Run: docuflow rewiki" });
|
|
194
|
+
}
|
|
195
|
+
// Old @doquflow/server pointing at dist/index.js instead of dist/mcp/index.js
|
|
196
|
+
for (const reg of registrations.filter(r => r.registered)) {
|
|
197
|
+
const argStr = reg.args?.join(" ") ?? "";
|
|
198
|
+
if (argStr.includes("@doquflow/server") && argStr.includes("dist/index.js")) {
|
|
199
|
+
recs.push({ severity: "info", message: `${reg.source}: MCP registration uses old server path`, action: "Run: docuflow init to refresh to @doquflow/studio/dist/mcp/index.js" });
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
if (recs.length === 0) {
|
|
203
|
+
recs.push({ severity: "info", message: "Everything looks good", action: "No action needed" });
|
|
204
|
+
}
|
|
205
|
+
return recs;
|
|
206
|
+
}
|
|
207
|
+
// ── Output formatters ─────────────────────────────────────────────────────────
|
|
208
|
+
function icon(severity) {
|
|
209
|
+
return severity === "error" ? "🔴" : severity === "warn" ? "🟡" : "🟢";
|
|
210
|
+
}
|
|
211
|
+
function printHuman(packages, registrations, workflow, health, recs, quiet) {
|
|
212
|
+
if (!quiet) {
|
|
213
|
+
// 1. Installed packages
|
|
214
|
+
console.log("\n── 1. Installed packages ────────────────────────────────");
|
|
215
|
+
for (const pkg of packages) {
|
|
216
|
+
const mark = pkg.version ? "✓" : "✗";
|
|
217
|
+
const ver = pkg.version ?? "not found";
|
|
218
|
+
console.log(` ${mark} ${pkg.name.padEnd(22)} ${ver}`);
|
|
219
|
+
}
|
|
220
|
+
// 2. MCP registrations
|
|
221
|
+
console.log("\n── 2. MCP server registrations ──────────────────────────");
|
|
222
|
+
for (const reg of registrations) {
|
|
223
|
+
const mark = reg.registered ? "✓" : "·";
|
|
224
|
+
const detail = reg.registered && reg.command
|
|
225
|
+
? ` ${reg.command} ${(reg.args ?? []).slice(-1)[0] ?? ""}`
|
|
226
|
+
: "";
|
|
227
|
+
console.log(` ${mark} ${reg.source.padEnd(18)}${reg.registered ? "registered" : "not registered"}${detail}`);
|
|
228
|
+
}
|
|
229
|
+
// 3. Workflow detection
|
|
230
|
+
console.log("\n── 3. Workflow detection ─────────────────────────────────");
|
|
231
|
+
console.log(` ${workflow.hasDocuflow ? "✓" : "✗"} .docuflow/ initialised`);
|
|
232
|
+
console.log(` ${workflow.hasSources ? "✓" : "·"} source documents present`);
|
|
233
|
+
console.log(` ${workflow.hasSpecs ? "✓" : "·"} specs written`);
|
|
234
|
+
console.log(` ${workflow.hasQueryUsage ? "✓" : "·"} query_wiki usage in logs`);
|
|
235
|
+
console.log(` ${workflow.watchRunning ? "✓" : "·"} watch daemon running`);
|
|
236
|
+
// 4. Health summary
|
|
237
|
+
console.log("\n── 5. Wiki health summary ───────────────────────────────");
|
|
238
|
+
console.log(` Pages total: ${health.totalPages}`);
|
|
239
|
+
if (health.totalPages > 0) {
|
|
240
|
+
for (const [cat, n] of Object.entries(health.byCategory)) {
|
|
241
|
+
if (n > 0)
|
|
242
|
+
console.log(` ${cat.padEnd(14)} ${n}`);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
console.log(` Last updated: ${health.lastUpdate}`);
|
|
246
|
+
console.log("");
|
|
247
|
+
}
|
|
248
|
+
// 4. Recommendations (always shown)
|
|
249
|
+
if (!quiet)
|
|
250
|
+
console.log("── 4. Recommendations ───────────────────────────────────");
|
|
251
|
+
for (const rec of recs) {
|
|
252
|
+
console.log(` ${icon(rec.severity)} ${rec.message}`);
|
|
253
|
+
console.log(` → ${rec.action}`);
|
|
254
|
+
}
|
|
255
|
+
console.log("");
|
|
256
|
+
}
|
|
257
|
+
// ── Entry point ───────────────────────────────────────────────────────────────
|
|
258
|
+
async function run(opts = {}) {
|
|
259
|
+
const projectPath = process.cwd();
|
|
260
|
+
const packages = getInstalledPackages();
|
|
261
|
+
const registrations = getMcpRegistrations(projectPath);
|
|
262
|
+
const workflow = detectWorkflow(projectPath);
|
|
263
|
+
const health = getHealthSummary(projectPath);
|
|
264
|
+
const recs = buildRecommendations(packages, registrations, workflow, health);
|
|
265
|
+
if (opts.json) {
|
|
266
|
+
console.log(JSON.stringify({ packages, registrations, workflow, health, recommendations: recs }, null, 2));
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
printHuman(packages, registrations, workflow, health, recs, opts.quiet ?? false);
|
|
270
|
+
}
|
package/dist/commands/help.js
CHANGED
|
@@ -13,6 +13,7 @@ function printCoreHelp() {
|
|
|
13
13
|
console.log(' docuflow query "<question>" Ask the wiki — answer with citations');
|
|
14
14
|
console.log(' docuflow status Show wiki health and counts');
|
|
15
15
|
console.log(' docuflow rewiki Migrate / re-ingest with current rules');
|
|
16
|
+
console.log(' docuflow doctor Diagnose install, MCP registration, and wiki health');
|
|
16
17
|
console.log('');
|
|
17
18
|
console.log('ADVANCED');
|
|
18
19
|
console.log(' docuflow advanced --help See watch / sync / ui / review / recent / suggest / update');
|
package/dist/commands/ingest.js
CHANGED
|
@@ -16,9 +16,12 @@ const c = {
|
|
|
16
16
|
};
|
|
17
17
|
function loadServerTool(toolFile) {
|
|
18
18
|
const candidates = [
|
|
19
|
-
() => require(`@doquflow/
|
|
20
|
-
() => require(node_path_1.default.resolve(__dirname, "../../../
|
|
21
|
-
() => require(node_path_1.default.resolve(__dirname, "../../
|
|
19
|
+
() => require(`@doquflow/core/dist/tools/${toolFile}`),
|
|
20
|
+
() => require(node_path_1.default.resolve(__dirname, "../../../core/dist/tools", toolFile)),
|
|
21
|
+
() => require(node_path_1.default.resolve(__dirname, "../../core/dist/tools", toolFile)),
|
|
22
|
+
() => require(`@doquflow/studio/dist/tools/${toolFile}`),
|
|
23
|
+
() => require(node_path_1.default.resolve(__dirname, "../../../studio/dist/tools", toolFile)),
|
|
24
|
+
() => require(node_path_1.default.resolve(__dirname, "../../studio/dist/tools", toolFile)),
|
|
22
25
|
];
|
|
23
26
|
for (const attempt of candidates) {
|
|
24
27
|
try {
|
package/dist/commands/init.js
CHANGED
|
@@ -62,13 +62,13 @@ function getCodexConfigPath() {
|
|
|
62
62
|
return node_path_1.default.join(node_os_1.default.homedir(), ".codex", "config.toml");
|
|
63
63
|
}
|
|
64
64
|
function resolveServerBin() {
|
|
65
|
-
// Try npm-installed
|
|
65
|
+
// Try npm-installed studio MCP binary first
|
|
66
66
|
try {
|
|
67
|
-
return require.resolve("@doquflow/
|
|
67
|
+
return require.resolve("@doquflow/studio/dist/mcp/index.js");
|
|
68
68
|
}
|
|
69
69
|
catch {
|
|
70
70
|
// Fallback: monorepo sibling path (dev environment)
|
|
71
|
-
return node_path_1.default.resolve(__dirname, "..", "..", "
|
|
71
|
+
return node_path_1.default.resolve(__dirname, "..", "..", "studio", "dist", "mcp", "index.js");
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
async function copyTemplateFile(templateName, destPath) {
|
package/dist/commands/query.js
CHANGED
|
@@ -36,9 +36,12 @@ const c = {
|
|
|
36
36
|
// ─── Dynamic server tool loader (mirrors rewiki.ts pattern) ───────────────────
|
|
37
37
|
function loadServerTool(toolFile) {
|
|
38
38
|
const candidates = [
|
|
39
|
-
() => require(`@doquflow/
|
|
40
|
-
() => require(node_path_1.default.resolve(__dirname, "../../../
|
|
41
|
-
() => require(node_path_1.default.resolve(__dirname, "../../
|
|
39
|
+
() => require(`@doquflow/core/dist/tools/${toolFile}`),
|
|
40
|
+
() => require(node_path_1.default.resolve(__dirname, "../../../core/dist/tools", toolFile)),
|
|
41
|
+
() => require(node_path_1.default.resolve(__dirname, "../../core/dist/tools", toolFile)),
|
|
42
|
+
() => require(`@doquflow/studio/dist/tools/${toolFile}`),
|
|
43
|
+
() => require(node_path_1.default.resolve(__dirname, "../../../studio/dist/tools", toolFile)),
|
|
44
|
+
() => require(node_path_1.default.resolve(__dirname, "../../studio/dist/tools", toolFile)),
|
|
42
45
|
];
|
|
43
46
|
for (const attempt of candidates) {
|
|
44
47
|
try {
|
package/dist/commands/rewiki.js
CHANGED
|
@@ -36,9 +36,12 @@ const c = {
|
|
|
36
36
|
// ─── Dynamic server tool loader (mirrors sync.ts pattern) ─────────────────────
|
|
37
37
|
function loadServerTool(toolFile) {
|
|
38
38
|
const candidates = [
|
|
39
|
-
() => require(`@doquflow/
|
|
40
|
-
() => require(node_path_1.default.resolve(__dirname, "../../../
|
|
41
|
-
() => require(node_path_1.default.resolve(__dirname, "../../
|
|
39
|
+
() => require(`@doquflow/core/dist/tools/${toolFile}`),
|
|
40
|
+
() => require(node_path_1.default.resolve(__dirname, "../../../core/dist/tools", toolFile)),
|
|
41
|
+
() => require(node_path_1.default.resolve(__dirname, "../../core/dist/tools", toolFile)),
|
|
42
|
+
() => require(`@doquflow/studio/dist/tools/${toolFile}`),
|
|
43
|
+
() => require(node_path_1.default.resolve(__dirname, "../../../studio/dist/tools", toolFile)),
|
|
44
|
+
() => require(node_path_1.default.resolve(__dirname, "../../studio/dist/tools", toolFile)),
|
|
42
45
|
];
|
|
43
46
|
for (const attempt of candidates) {
|
|
44
47
|
try {
|
package/dist/commands/sync.js
CHANGED
|
@@ -39,9 +39,14 @@ const c = {
|
|
|
39
39
|
// ─── Dynamic server tool loader ────────────────────────────────────────────────
|
|
40
40
|
function loadServerTool(toolFile) {
|
|
41
41
|
const candidates = [
|
|
42
|
-
|
|
43
|
-
() => require(
|
|
44
|
-
() => require(node_path_1.default.resolve(__dirname, "
|
|
42
|
+
// v2.0 — 4 core tools live in @doquflow/core
|
|
43
|
+
() => require(`@doquflow/core/dist/tools/${toolFile}`),
|
|
44
|
+
() => require(node_path_1.default.resolve(__dirname, "../../../core/dist/tools", toolFile)),
|
|
45
|
+
() => require(node_path_1.default.resolve(__dirname, "../../core/dist/tools", toolFile)),
|
|
46
|
+
// v2.0 — 11 advanced tools live in @doquflow/studio
|
|
47
|
+
() => require(`@doquflow/studio/dist/tools/${toolFile}`),
|
|
48
|
+
() => require(node_path_1.default.resolve(__dirname, "../../../studio/dist/tools", toolFile)),
|
|
49
|
+
() => require(node_path_1.default.resolve(__dirname, "../../studio/dist/tools", toolFile)),
|
|
45
50
|
];
|
|
46
51
|
for (const attempt of candidates) {
|
|
47
52
|
try {
|
|
@@ -135,10 +140,10 @@ function runClaudeSync(prompt, projectPath, allowDangerousPermissions = false) {
|
|
|
135
140
|
// Build the MCP config pointing to the local server binary
|
|
136
141
|
let serverBin;
|
|
137
142
|
try {
|
|
138
|
-
serverBin = require.resolve("@doquflow/
|
|
143
|
+
serverBin = require.resolve("@doquflow/studio/dist/mcp/index.js");
|
|
139
144
|
}
|
|
140
145
|
catch {
|
|
141
|
-
serverBin = node_path_1.default.resolve(__dirname, "../../
|
|
146
|
+
serverBin = node_path_1.default.resolve(__dirname, "../../studio/dist/mcp/index.js");
|
|
142
147
|
}
|
|
143
148
|
const mcpConfig = JSON.stringify({
|
|
144
149
|
mcpServers: {
|
package/dist/commands/ui.js
CHANGED
|
@@ -27,7 +27,7 @@ const init_1 = require("./init");
|
|
|
27
27
|
const watch_1 = require("./watch");
|
|
28
28
|
function loadTool(file, exportName) {
|
|
29
29
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
30
|
-
return require(`@doquflow/
|
|
30
|
+
return require(`@doquflow/studio/dist/tools/${file}`)[exportName];
|
|
31
31
|
}
|
|
32
32
|
// ── Helpers ───────────────────────────────────────────────────────────────────
|
|
33
33
|
async function findDocuflowProjects(scanRoot) {
|
package/dist/commands/update.js
CHANGED
|
@@ -102,7 +102,7 @@ async function run(opts = {}) {
|
|
|
102
102
|
process.exit(result.status ?? 1);
|
|
103
103
|
}
|
|
104
104
|
console.log(`\n✓ Updated to ${latest}.`);
|
|
105
|
-
console.log(` This refreshed the CLI, bundled UI (ui-dist), and the @doquflow/
|
|
105
|
+
console.log(` This refreshed the CLI, bundled UI (ui-dist), and the @doquflow/core + @doquflow/studio dependencies.`);
|
|
106
106
|
const stale = await isPortInUse(DEFAULT_PORT);
|
|
107
107
|
if (stale) {
|
|
108
108
|
console.log('');
|
package/dist/commands/watch.js
CHANGED
|
@@ -54,9 +54,12 @@ const node_child_process_1 = require("node:child_process");
|
|
|
54
54
|
// ─── Dynamic server tool loader ────────────────────────────────────────────────
|
|
55
55
|
function loadServerTool(toolFile) {
|
|
56
56
|
const candidates = [
|
|
57
|
-
() => require(`@doquflow/
|
|
58
|
-
() => require(node_path_1.default.resolve(__dirname, "../../../
|
|
59
|
-
() => require(node_path_1.default.resolve(__dirname, "../../
|
|
57
|
+
() => require(`@doquflow/core/dist/tools/${toolFile}`),
|
|
58
|
+
() => require(node_path_1.default.resolve(__dirname, "../../../core/dist/tools", toolFile)),
|
|
59
|
+
() => require(node_path_1.default.resolve(__dirname, "../../core/dist/tools", toolFile)),
|
|
60
|
+
() => require(`@doquflow/studio/dist/tools/${toolFile}`),
|
|
61
|
+
() => require(node_path_1.default.resolve(__dirname, "../../../studio/dist/tools", toolFile)),
|
|
62
|
+
() => require(node_path_1.default.resolve(__dirname, "../../studio/dist/tools", toolFile)),
|
|
60
63
|
];
|
|
61
64
|
for (const attempt of candidates) {
|
|
62
65
|
try {
|
|
@@ -202,10 +205,10 @@ let _allowDangerousPermissions = false;
|
|
|
202
205
|
function runClaudeCLI(prompt, timeoutMs = 120_000) {
|
|
203
206
|
let serverBin;
|
|
204
207
|
try {
|
|
205
|
-
serverBin = require.resolve("@doquflow/
|
|
208
|
+
serverBin = require.resolve("@doquflow/studio/dist/mcp/index.js");
|
|
206
209
|
}
|
|
207
210
|
catch {
|
|
208
|
-
serverBin = node_path_1.default.resolve(__dirname, "../../
|
|
211
|
+
serverBin = node_path_1.default.resolve(__dirname, "../../studio/dist/mcp/index.js");
|
|
209
212
|
}
|
|
210
213
|
const mcpConfig = JSON.stringify({
|
|
211
214
|
mcpServers: { docuflow: { type: "stdio", command: process.execPath, args: [serverBin] } }
|
package/dist/index.js
CHANGED
|
@@ -100,6 +100,13 @@ function dispatch(c, r) {
|
|
|
100
100
|
noBackup: hasFlagIn(r, '--no-backup'),
|
|
101
101
|
quiet: hasFlagIn(r, '--quiet', '-q'),
|
|
102
102
|
}));
|
|
103
|
+
// ── doctor — diagnose install, MCP registration, and wiki health ──────────
|
|
104
|
+
}
|
|
105
|
+
else if (c === 'doctor') {
|
|
106
|
+
Promise.resolve().then(() => __importStar(require('./commands/doctor'))).then(m => m.run({
|
|
107
|
+
json: hasFlagIn(r, '--json'),
|
|
108
|
+
quiet: hasFlagIn(r, '--quiet', '-q'),
|
|
109
|
+
}));
|
|
103
110
|
// ── ADVANCED ──────────────────────────────────────────────────────────────
|
|
104
111
|
}
|
|
105
112
|
else if (c === 'suggest') {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@doquflow/cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "CLI for setting up Docuflow in your project",
|
|
5
5
|
"author": "Docuflow <hello@doquflows.dev>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -28,10 +28,11 @@
|
|
|
28
28
|
"README.md"
|
|
29
29
|
],
|
|
30
30
|
"scripts": {
|
|
31
|
-
"build": "tsc && node -e \"const fs=require('fs'),p=require('path'),src=p.join(process.cwd(),'../ui
|
|
31
|
+
"build": "tsc && node -e \"const fs=require('fs'),p=require('path'),src=p.join(process.cwd(),'../studio/ui-dist'),dst=p.join(process.cwd(),'ui-dist');if(!fs.existsSync(src)){console.log('Warning: packages/studio/ui-dist not found — run npm run build:ui -w packages/studio first');process.exit(0)}fs.mkdirSync(dst,{recursive:true});fs.cpSync(src,dst,{recursive:true,force:true});console.log(' ✓ ui-dist synced from packages/studio/ui-dist ('+(fs.readdirSync(dst).length)+' files at root)')\""
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@doquflow/
|
|
34
|
+
"@doquflow/core": "2.0.0",
|
|
35
|
+
"@doquflow/studio": "2.0.0",
|
|
35
36
|
"cors": "^2.8.5",
|
|
36
37
|
"express": "^4.19.2"
|
|
37
38
|
},
|