@nicnocquee/dataqueue 1.33.0 → 1.34.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/ai/build-docs-content.ts +96 -0
- package/ai/build-llms-full.ts +42 -0
- package/ai/docs-content.json +278 -0
- package/ai/rules/advanced.md +94 -0
- package/ai/rules/basic.md +90 -0
- package/ai/rules/react-dashboard.md +83 -0
- package/ai/skills/dataqueue-advanced/SKILL.md +211 -0
- package/ai/skills/dataqueue-core/SKILL.md +131 -0
- package/ai/skills/dataqueue-react/SKILL.md +189 -0
- package/dist/cli.cjs +577 -32
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.d.cts +52 -2
- package/dist/cli.d.ts +52 -2
- package/dist/cli.js +575 -32
- package/dist/cli.js.map +1 -1
- package/dist/mcp-server.cjs +186 -0
- package/dist/mcp-server.cjs.map +1 -0
- package/dist/mcp-server.d.cts +32 -0
- package/dist/mcp-server.d.ts +32 -0
- package/dist/mcp-server.js +175 -0
- package/dist/mcp-server.js.map +1 -0
- package/package.json +10 -4
- package/src/cli.test.ts +65 -0
- package/src/cli.ts +56 -19
- package/src/install-mcp-command.test.ts +216 -0
- package/src/install-mcp-command.ts +185 -0
- package/src/install-rules-command.test.ts +218 -0
- package/src/install-rules-command.ts +233 -0
- package/src/install-skills-command.test.ts +176 -0
- package/src/install-skills-command.ts +124 -0
- package/src/mcp-server.test.ts +162 -0
- package/src/mcp-server.ts +231 -0
package/dist/cli.cjs
CHANGED
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var child_process = require('child_process');
|
|
4
|
-
var
|
|
4
|
+
var path3 = require('path');
|
|
5
5
|
var url = require('url');
|
|
6
6
|
var fs = require('fs');
|
|
7
|
+
var readline = require('readline');
|
|
8
|
+
var mcp_js = require('@modelcontextprotocol/sdk/server/mcp.js');
|
|
9
|
+
var stdio_js = require('@modelcontextprotocol/sdk/server/stdio.js');
|
|
10
|
+
var zod = require('zod');
|
|
7
11
|
|
|
8
12
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
9
13
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
14
|
|
|
11
|
-
var
|
|
15
|
+
var path3__default = /*#__PURE__*/_interopDefault(path3);
|
|
16
|
+
var fs__default = /*#__PURE__*/_interopDefault(fs);
|
|
17
|
+
var readline__default = /*#__PURE__*/_interopDefault(readline);
|
|
12
18
|
|
|
13
19
|
// src/cli.ts
|
|
14
20
|
var DEPENDENCIES_TO_ADD = [
|
|
@@ -373,7 +379,7 @@ function detectNextJsAndRouter({
|
|
|
373
379
|
existsSyncImpl,
|
|
374
380
|
readFileSyncImpl
|
|
375
381
|
}) {
|
|
376
|
-
const packageJsonPath =
|
|
382
|
+
const packageJsonPath = path3__default.default.join(cwd, "package.json");
|
|
377
383
|
if (!existsSyncImpl(packageJsonPath)) {
|
|
378
384
|
throw new Error("package.json not found in current directory.");
|
|
379
385
|
}
|
|
@@ -386,10 +392,10 @@ function detectNextJsAndRouter({
|
|
|
386
392
|
"Not a Next.js project. Could not find 'next' in package.json dependencies."
|
|
387
393
|
);
|
|
388
394
|
}
|
|
389
|
-
const srcDir =
|
|
395
|
+
const srcDir = path3__default.default.join(cwd, "src");
|
|
390
396
|
const srcRoot = existsSyncImpl(srcDir) ? "src" : ".";
|
|
391
|
-
const appDir =
|
|
392
|
-
const pagesDir =
|
|
397
|
+
const appDir = path3__default.default.join(cwd, srcRoot, "app");
|
|
398
|
+
const pagesDir = path3__default.default.join(cwd, srcRoot, "pages");
|
|
393
399
|
const hasAppDir = existsSyncImpl(appDir);
|
|
394
400
|
const hasPagesDir = existsSyncImpl(pagesDir);
|
|
395
401
|
if (!hasAppDir && !hasPagesDir) {
|
|
@@ -450,7 +456,7 @@ function createScaffoldFiles({
|
|
|
450
456
|
writeFileSyncImpl,
|
|
451
457
|
chmodSyncImpl
|
|
452
458
|
}) {
|
|
453
|
-
const appRoutePath =
|
|
459
|
+
const appRoutePath = path3__default.default.join(
|
|
454
460
|
details.cwd,
|
|
455
461
|
details.srcRoot,
|
|
456
462
|
"app",
|
|
@@ -460,7 +466,7 @@ function createScaffoldFiles({
|
|
|
460
466
|
"[[...task]]",
|
|
461
467
|
"route.ts"
|
|
462
468
|
);
|
|
463
|
-
const pagesRoutePath =
|
|
469
|
+
const pagesRoutePath = path3__default.default.join(
|
|
464
470
|
details.cwd,
|
|
465
471
|
details.srcRoot,
|
|
466
472
|
"pages",
|
|
@@ -469,14 +475,14 @@ function createScaffoldFiles({
|
|
|
469
475
|
"manage",
|
|
470
476
|
"[[...task]].ts"
|
|
471
477
|
);
|
|
472
|
-
const queuePath =
|
|
478
|
+
const queuePath = path3__default.default.join(
|
|
473
479
|
details.cwd,
|
|
474
480
|
details.srcRoot,
|
|
475
481
|
"lib",
|
|
476
482
|
"dataqueue",
|
|
477
483
|
"queue.ts"
|
|
478
484
|
);
|
|
479
|
-
const cronPath =
|
|
485
|
+
const cronPath = path3__default.default.join(details.cwd, "cron.sh");
|
|
480
486
|
if (details.router === "app") {
|
|
481
487
|
createFileIfMissing({
|
|
482
488
|
absolutePath: appRoutePath,
|
|
@@ -539,7 +545,7 @@ function createFileIfMissing({
|
|
|
539
545
|
log(` [skipped] ${logPath} (already exists)`);
|
|
540
546
|
return;
|
|
541
547
|
}
|
|
542
|
-
mkdirSyncImpl(
|
|
548
|
+
mkdirSyncImpl(path3__default.default.dirname(absolutePath), { recursive: true });
|
|
543
549
|
writeFileSyncImpl(absolutePath, content);
|
|
544
550
|
log(` [created] ${logPath}`);
|
|
545
551
|
}
|
|
@@ -575,21 +581,541 @@ function ensureStringMapSection(packageJson, sectionName) {
|
|
|
575
581
|
return packageJson[sectionName];
|
|
576
582
|
}
|
|
577
583
|
function toRelativePath(cwd, absolutePath) {
|
|
578
|
-
const relative =
|
|
584
|
+
const relative = path3__default.default.relative(cwd, absolutePath);
|
|
579
585
|
return relative || ".";
|
|
580
586
|
}
|
|
587
|
+
var __filename$1 = url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli.cjs', document.baseURI).href)));
|
|
588
|
+
var __dirname$1 = path3__default.default.dirname(__filename$1);
|
|
589
|
+
var SKILL_DIRS = ["dataqueue-core", "dataqueue-advanced", "dataqueue-react"];
|
|
590
|
+
function detectAiTools(cwd, existsSync2 = fs__default.default.existsSync) {
|
|
591
|
+
const tools = [];
|
|
592
|
+
const checks = [
|
|
593
|
+
{
|
|
594
|
+
name: "Cursor",
|
|
595
|
+
indicator: ".cursor",
|
|
596
|
+
targetDir: ".cursor/skills"
|
|
597
|
+
},
|
|
598
|
+
{
|
|
599
|
+
name: "Claude Code",
|
|
600
|
+
indicator: ".claude",
|
|
601
|
+
targetDir: ".claude/skills"
|
|
602
|
+
},
|
|
603
|
+
{
|
|
604
|
+
name: "GitHub Copilot",
|
|
605
|
+
indicator: ".github",
|
|
606
|
+
targetDir: ".github/skills"
|
|
607
|
+
}
|
|
608
|
+
];
|
|
609
|
+
for (const check of checks) {
|
|
610
|
+
if (existsSync2(path3__default.default.join(cwd, check.indicator))) {
|
|
611
|
+
tools.push({ name: check.name, targetDir: check.targetDir });
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
return tools;
|
|
615
|
+
}
|
|
616
|
+
function runInstallSkills({
|
|
617
|
+
log = console.log,
|
|
618
|
+
error = console.error,
|
|
619
|
+
exit = (code) => process.exit(code),
|
|
620
|
+
cwd = process.cwd(),
|
|
621
|
+
existsSync: existsSync2 = fs__default.default.existsSync,
|
|
622
|
+
mkdirSync: mkdirSync2 = fs__default.default.mkdirSync,
|
|
623
|
+
copyFileSync = fs__default.default.copyFileSync,
|
|
624
|
+
readdirSync = fs__default.default.readdirSync,
|
|
625
|
+
skillsSourceDir = path3__default.default.join(__dirname$1, "../ai/skills")
|
|
626
|
+
} = {}) {
|
|
627
|
+
const tools = detectAiTools(cwd, existsSync2);
|
|
628
|
+
if (tools.length === 0) {
|
|
629
|
+
log("No AI tool directories detected (.cursor/, .claude/, .github/).");
|
|
630
|
+
log("Creating .cursor/skills/ as the default target.");
|
|
631
|
+
tools.push({ name: "Cursor", targetDir: ".cursor/skills" });
|
|
632
|
+
}
|
|
633
|
+
let installed = 0;
|
|
634
|
+
for (const tool of tools) {
|
|
635
|
+
log(`
|
|
636
|
+
Installing skills for ${tool.name}...`);
|
|
637
|
+
for (const skillDir of SKILL_DIRS) {
|
|
638
|
+
const srcDir = path3__default.default.join(skillsSourceDir, skillDir);
|
|
639
|
+
const destDir = path3__default.default.join(cwd, tool.targetDir, skillDir);
|
|
640
|
+
try {
|
|
641
|
+
mkdirSync2(destDir, { recursive: true });
|
|
642
|
+
const files = readdirSync(srcDir);
|
|
643
|
+
for (const file of files) {
|
|
644
|
+
copyFileSync(path3__default.default.join(srcDir, file), path3__default.default.join(destDir, file));
|
|
645
|
+
}
|
|
646
|
+
log(` \u2713 ${skillDir}`);
|
|
647
|
+
installed++;
|
|
648
|
+
} catch (err) {
|
|
649
|
+
error(` \u2717 Failed to install ${skillDir}:`, err);
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
if (installed > 0) {
|
|
654
|
+
log(
|
|
655
|
+
`
|
|
656
|
+
Done! Installed ${installed} skill(s) for ${tools.map((t) => t.name).join(", ")}.`
|
|
657
|
+
);
|
|
658
|
+
} else {
|
|
659
|
+
error("No skills were installed.");
|
|
660
|
+
exit(1);
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
var __filename2 = url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli.cjs', document.baseURI).href)));
|
|
664
|
+
var __dirname2 = path3__default.default.dirname(__filename2);
|
|
665
|
+
var RULE_FILES = ["basic.md", "advanced.md", "react-dashboard.md"];
|
|
666
|
+
var MARKER_START = "<!-- DATAQUEUE RULES START -->";
|
|
667
|
+
var MARKER_END = "<!-- DATAQUEUE RULES END -->";
|
|
668
|
+
function upsertMarkedSection(filePath, content, deps) {
|
|
669
|
+
const block = `${MARKER_START}
|
|
670
|
+
${content}
|
|
671
|
+
${MARKER_END}`;
|
|
672
|
+
if (!deps.existsSync(filePath)) {
|
|
673
|
+
deps.writeFileSync(filePath, block + "\n");
|
|
674
|
+
return;
|
|
675
|
+
}
|
|
676
|
+
const existing = deps.readFileSync(filePath, "utf-8");
|
|
677
|
+
const startIdx = existing.indexOf(MARKER_START);
|
|
678
|
+
const endIdx = existing.indexOf(MARKER_END);
|
|
679
|
+
if (startIdx !== -1 && endIdx !== -1) {
|
|
680
|
+
const before = existing.slice(0, startIdx);
|
|
681
|
+
const after = existing.slice(endIdx + MARKER_END.length);
|
|
682
|
+
deps.writeFileSync(filePath, before + block + after);
|
|
683
|
+
} else {
|
|
684
|
+
deps.writeFileSync(filePath, existing.trimEnd() + "\n\n" + block + "\n");
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
function getAllRulesContent(rulesSourceDir, readFileSync2) {
|
|
688
|
+
return RULE_FILES.map(
|
|
689
|
+
(f) => readFileSync2(path3__default.default.join(rulesSourceDir, f), "utf-8")
|
|
690
|
+
).join("\n\n");
|
|
691
|
+
}
|
|
692
|
+
var CLIENTS = {
|
|
693
|
+
"1": {
|
|
694
|
+
label: "Cursor",
|
|
695
|
+
install: (deps) => {
|
|
696
|
+
const rulesDir = path3__default.default.join(deps.cwd, ".cursor", "rules");
|
|
697
|
+
deps.mkdirSync(rulesDir, { recursive: true });
|
|
698
|
+
for (const file of RULE_FILES) {
|
|
699
|
+
const src = deps.readFileSync(
|
|
700
|
+
path3__default.default.join(deps.rulesSourceDir, file),
|
|
701
|
+
"utf-8"
|
|
702
|
+
);
|
|
703
|
+
const destName = `dataqueue-${file.replace(/\.md$/, ".mdc")}`;
|
|
704
|
+
deps.writeFileSync(path3__default.default.join(rulesDir, destName), src);
|
|
705
|
+
deps.log(` \u2713 .cursor/rules/${destName}`);
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
},
|
|
709
|
+
"2": {
|
|
710
|
+
label: "Claude Code",
|
|
711
|
+
install: (deps) => {
|
|
712
|
+
const content = getAllRulesContent(
|
|
713
|
+
deps.rulesSourceDir,
|
|
714
|
+
deps.readFileSync
|
|
715
|
+
);
|
|
716
|
+
const filePath = path3__default.default.join(deps.cwd, "CLAUDE.md");
|
|
717
|
+
upsertMarkedSection(filePath, content, deps);
|
|
718
|
+
deps.log(` \u2713 CLAUDE.md`);
|
|
719
|
+
}
|
|
720
|
+
},
|
|
721
|
+
"3": {
|
|
722
|
+
label: "AGENTS.md (Codex, Jules, OpenCode)",
|
|
723
|
+
install: (deps) => {
|
|
724
|
+
const content = getAllRulesContent(
|
|
725
|
+
deps.rulesSourceDir,
|
|
726
|
+
deps.readFileSync
|
|
727
|
+
);
|
|
728
|
+
const filePath = path3__default.default.join(deps.cwd, "AGENTS.md");
|
|
729
|
+
upsertMarkedSection(filePath, content, deps);
|
|
730
|
+
deps.log(` \u2713 AGENTS.md`);
|
|
731
|
+
}
|
|
732
|
+
},
|
|
733
|
+
"4": {
|
|
734
|
+
label: "GitHub Copilot",
|
|
735
|
+
install: (deps) => {
|
|
736
|
+
const content = getAllRulesContent(
|
|
737
|
+
deps.rulesSourceDir,
|
|
738
|
+
deps.readFileSync
|
|
739
|
+
);
|
|
740
|
+
deps.mkdirSync(path3__default.default.join(deps.cwd, ".github"), { recursive: true });
|
|
741
|
+
const filePath = path3__default.default.join(
|
|
742
|
+
deps.cwd,
|
|
743
|
+
".github",
|
|
744
|
+
"copilot-instructions.md"
|
|
745
|
+
);
|
|
746
|
+
upsertMarkedSection(filePath, content, deps);
|
|
747
|
+
deps.log(` \u2713 .github/copilot-instructions.md`);
|
|
748
|
+
}
|
|
749
|
+
},
|
|
750
|
+
"5": {
|
|
751
|
+
label: "Windsurf",
|
|
752
|
+
install: (deps) => {
|
|
753
|
+
const content = getAllRulesContent(
|
|
754
|
+
deps.rulesSourceDir,
|
|
755
|
+
deps.readFileSync
|
|
756
|
+
);
|
|
757
|
+
const filePath = path3__default.default.join(deps.cwd, "CONVENTIONS.md");
|
|
758
|
+
upsertMarkedSection(filePath, content, deps);
|
|
759
|
+
deps.log(` \u2713 CONVENTIONS.md`);
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
};
|
|
763
|
+
async function runInstallRules({
|
|
764
|
+
log = console.log,
|
|
765
|
+
error = console.error,
|
|
766
|
+
exit = (code) => process.exit(code),
|
|
767
|
+
cwd = process.cwd(),
|
|
768
|
+
readFileSync: readFileSync2 = fs__default.default.readFileSync,
|
|
769
|
+
writeFileSync: writeFileSync2 = fs__default.default.writeFileSync,
|
|
770
|
+
appendFileSync = fs__default.default.appendFileSync,
|
|
771
|
+
mkdirSync: mkdirSync2 = fs__default.default.mkdirSync,
|
|
772
|
+
existsSync: existsSync2 = fs__default.default.existsSync,
|
|
773
|
+
rulesSourceDir = path3__default.default.join(__dirname2, "../ai/rules"),
|
|
774
|
+
selectedClient
|
|
775
|
+
} = {}) {
|
|
776
|
+
log("DataQueue Agent Rules Installer\n");
|
|
777
|
+
log("Select your AI client:\n");
|
|
778
|
+
for (const [key, client2] of Object.entries(CLIENTS)) {
|
|
779
|
+
log(` ${key}) ${client2.label}`);
|
|
780
|
+
}
|
|
781
|
+
log("");
|
|
782
|
+
let choice = selectedClient;
|
|
783
|
+
if (!choice) {
|
|
784
|
+
const rl = readline__default.default.createInterface({
|
|
785
|
+
input: process.stdin,
|
|
786
|
+
output: process.stdout
|
|
787
|
+
});
|
|
788
|
+
choice = await new Promise((resolve) => {
|
|
789
|
+
rl.question("Enter choice (1-5): ", (answer) => {
|
|
790
|
+
rl.close();
|
|
791
|
+
resolve(answer.trim());
|
|
792
|
+
});
|
|
793
|
+
});
|
|
794
|
+
}
|
|
795
|
+
const client = CLIENTS[choice];
|
|
796
|
+
if (!client) {
|
|
797
|
+
error(`Invalid choice: "${choice}". Expected 1-5.`);
|
|
798
|
+
exit(1);
|
|
799
|
+
return;
|
|
800
|
+
}
|
|
801
|
+
log(`
|
|
802
|
+
Installing rules for ${client.label}...`);
|
|
803
|
+
try {
|
|
804
|
+
client.install({
|
|
805
|
+
cwd,
|
|
806
|
+
readFileSync: readFileSync2,
|
|
807
|
+
writeFileSync: writeFileSync2,
|
|
808
|
+
appendFileSync,
|
|
809
|
+
mkdirSync: mkdirSync2,
|
|
810
|
+
existsSync: existsSync2,
|
|
811
|
+
log,
|
|
812
|
+
rulesSourceDir
|
|
813
|
+
});
|
|
814
|
+
log("\nDone!");
|
|
815
|
+
} catch (err) {
|
|
816
|
+
error("Failed to install rules:", err);
|
|
817
|
+
exit(1);
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
function upsertMcpConfig(filePath, serverKey, serverConfig, deps) {
|
|
821
|
+
let config = {};
|
|
822
|
+
if (deps.existsSync(filePath)) {
|
|
823
|
+
try {
|
|
824
|
+
config = JSON.parse(deps.readFileSync(filePath, "utf-8"));
|
|
825
|
+
} catch {
|
|
826
|
+
config = {};
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
if (!config.mcpServers || typeof config.mcpServers !== "object") {
|
|
830
|
+
config.mcpServers = {};
|
|
831
|
+
}
|
|
832
|
+
config.mcpServers[serverKey] = serverConfig;
|
|
833
|
+
deps.writeFileSync(filePath, JSON.stringify(config, null, 2) + "\n");
|
|
834
|
+
}
|
|
835
|
+
var MCP_SERVER_CONFIG = {
|
|
836
|
+
command: "npx",
|
|
837
|
+
args: ["dataqueue-cli", "mcp"]
|
|
838
|
+
};
|
|
839
|
+
var MCP_CLIENTS = {
|
|
840
|
+
"1": {
|
|
841
|
+
label: "Cursor",
|
|
842
|
+
install: (deps) => {
|
|
843
|
+
const configDir = path3__default.default.join(deps.cwd, ".cursor");
|
|
844
|
+
deps.mkdirSync(configDir, { recursive: true });
|
|
845
|
+
const configFile = path3__default.default.join(configDir, "mcp.json");
|
|
846
|
+
upsertMcpConfig(configFile, "dataqueue", MCP_SERVER_CONFIG, deps);
|
|
847
|
+
deps.log(` \u2713 .cursor/mcp.json`);
|
|
848
|
+
}
|
|
849
|
+
},
|
|
850
|
+
"2": {
|
|
851
|
+
label: "Claude Code",
|
|
852
|
+
install: (deps) => {
|
|
853
|
+
const configFile = path3__default.default.join(deps.cwd, ".mcp.json");
|
|
854
|
+
upsertMcpConfig(configFile, "dataqueue", MCP_SERVER_CONFIG, deps);
|
|
855
|
+
deps.log(` \u2713 .mcp.json`);
|
|
856
|
+
}
|
|
857
|
+
},
|
|
858
|
+
"3": {
|
|
859
|
+
label: "VS Code (Copilot)",
|
|
860
|
+
install: (deps) => {
|
|
861
|
+
const configDir = path3__default.default.join(deps.cwd, ".vscode");
|
|
862
|
+
deps.mkdirSync(configDir, { recursive: true });
|
|
863
|
+
const configFile = path3__default.default.join(configDir, "mcp.json");
|
|
864
|
+
upsertMcpConfig(configFile, "dataqueue", MCP_SERVER_CONFIG, deps);
|
|
865
|
+
deps.log(` \u2713 .vscode/mcp.json`);
|
|
866
|
+
}
|
|
867
|
+
},
|
|
868
|
+
"4": {
|
|
869
|
+
label: "Windsurf",
|
|
870
|
+
install: (deps) => {
|
|
871
|
+
const homeDir = process.env.HOME || process.env.USERPROFILE || "";
|
|
872
|
+
const configFile = path3__default.default.join(
|
|
873
|
+
homeDir,
|
|
874
|
+
".codeium",
|
|
875
|
+
"windsurf",
|
|
876
|
+
"mcp_config.json"
|
|
877
|
+
);
|
|
878
|
+
deps.mkdirSync(path3__default.default.dirname(configFile), { recursive: true });
|
|
879
|
+
upsertMcpConfig(configFile, "dataqueue", MCP_SERVER_CONFIG, deps);
|
|
880
|
+
deps.log(` \u2713 ~/.codeium/windsurf/mcp_config.json`);
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
};
|
|
884
|
+
async function runInstallMcp({
|
|
885
|
+
log = console.log,
|
|
886
|
+
error = console.error,
|
|
887
|
+
exit = (code) => process.exit(code),
|
|
888
|
+
cwd = process.cwd(),
|
|
889
|
+
readFileSync: readFileSync2 = fs__default.default.readFileSync,
|
|
890
|
+
writeFileSync: writeFileSync2 = fs__default.default.writeFileSync,
|
|
891
|
+
mkdirSync: mkdirSync2 = fs__default.default.mkdirSync,
|
|
892
|
+
existsSync: existsSync2 = fs__default.default.existsSync,
|
|
893
|
+
selectedClient
|
|
894
|
+
} = {}) {
|
|
895
|
+
log("DataQueue MCP Server Installer\n");
|
|
896
|
+
log("Select your AI client:\n");
|
|
897
|
+
for (const [key, client2] of Object.entries(MCP_CLIENTS)) {
|
|
898
|
+
log(` ${key}) ${client2.label}`);
|
|
899
|
+
}
|
|
900
|
+
log("");
|
|
901
|
+
let choice = selectedClient;
|
|
902
|
+
if (!choice) {
|
|
903
|
+
const rl = readline__default.default.createInterface({
|
|
904
|
+
input: process.stdin,
|
|
905
|
+
output: process.stdout
|
|
906
|
+
});
|
|
907
|
+
choice = await new Promise((resolve) => {
|
|
908
|
+
rl.question("Enter choice (1-4): ", (answer) => {
|
|
909
|
+
rl.close();
|
|
910
|
+
resolve(answer.trim());
|
|
911
|
+
});
|
|
912
|
+
});
|
|
913
|
+
}
|
|
914
|
+
const client = MCP_CLIENTS[choice];
|
|
915
|
+
if (!client) {
|
|
916
|
+
error(`Invalid choice: "${choice}". Expected 1-4.`);
|
|
917
|
+
exit(1);
|
|
918
|
+
return;
|
|
919
|
+
}
|
|
920
|
+
log(`
|
|
921
|
+
Installing MCP config for ${client.label}...`);
|
|
922
|
+
try {
|
|
923
|
+
client.install({
|
|
924
|
+
cwd,
|
|
925
|
+
readFileSync: readFileSync2,
|
|
926
|
+
writeFileSync: writeFileSync2,
|
|
927
|
+
mkdirSync: mkdirSync2,
|
|
928
|
+
existsSync: existsSync2,
|
|
929
|
+
log
|
|
930
|
+
});
|
|
931
|
+
log("\nDone! The MCP server will run via: npx dataqueue-cli mcp");
|
|
932
|
+
} catch (err) {
|
|
933
|
+
error("Failed to install MCP config:", err);
|
|
934
|
+
exit(1);
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
var __filename3 = url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli.cjs', document.baseURI).href)));
|
|
938
|
+
var __dirname3 = path3__default.default.dirname(__filename3);
|
|
939
|
+
function loadDocsContent(docsPath = path3__default.default.join(__dirname3, "../ai/docs-content.json")) {
|
|
940
|
+
const raw = fs__default.default.readFileSync(docsPath, "utf-8");
|
|
941
|
+
return JSON.parse(raw);
|
|
942
|
+
}
|
|
943
|
+
function scorePageForQuery(page, queryTerms) {
|
|
944
|
+
const titleLower = page.title.toLowerCase();
|
|
945
|
+
const descLower = page.description.toLowerCase();
|
|
946
|
+
const contentLower = page.content.toLowerCase();
|
|
947
|
+
let score = 0;
|
|
948
|
+
for (const term of queryTerms) {
|
|
949
|
+
if (titleLower.includes(term)) score += 10;
|
|
950
|
+
if (descLower.includes(term)) score += 5;
|
|
951
|
+
const contentMatches = contentLower.split(term).length - 1;
|
|
952
|
+
score += Math.min(contentMatches, 10);
|
|
953
|
+
}
|
|
954
|
+
return score;
|
|
955
|
+
}
|
|
956
|
+
function extractExcerpt(content, queryTerms, maxLength = 500) {
|
|
957
|
+
const lower = content.toLowerCase();
|
|
958
|
+
let earliestIndex = -1;
|
|
959
|
+
for (const term of queryTerms) {
|
|
960
|
+
const idx = lower.indexOf(term);
|
|
961
|
+
if (idx !== -1 && (earliestIndex === -1 || idx < earliestIndex)) {
|
|
962
|
+
earliestIndex = idx;
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
if (earliestIndex === -1) {
|
|
966
|
+
return content.slice(0, maxLength);
|
|
967
|
+
}
|
|
968
|
+
const start = Math.max(0, earliestIndex - 100);
|
|
969
|
+
const end = Math.min(content.length, start + maxLength);
|
|
970
|
+
let excerpt = content.slice(start, end);
|
|
971
|
+
if (start > 0) excerpt = "..." + excerpt;
|
|
972
|
+
if (end < content.length) excerpt = excerpt + "...";
|
|
973
|
+
return excerpt;
|
|
974
|
+
}
|
|
975
|
+
async function startMcpServer(deps = {}) {
|
|
976
|
+
const pages = loadDocsContent(deps.docsPath);
|
|
977
|
+
const server = new mcp_js.McpServer({
|
|
978
|
+
name: "dataqueue-docs",
|
|
979
|
+
version: "1.0.0"
|
|
980
|
+
});
|
|
981
|
+
server.resource("llms-txt", "dataqueue://llms.txt", async () => {
|
|
982
|
+
const llmsPath = path3__default.default.join(
|
|
983
|
+
__dirname3,
|
|
984
|
+
"../ai/skills/dataqueue-core/SKILL.md"
|
|
985
|
+
);
|
|
986
|
+
let content;
|
|
987
|
+
try {
|
|
988
|
+
content = fs__default.default.readFileSync(llmsPath, "utf-8");
|
|
989
|
+
} catch {
|
|
990
|
+
content = pages.map((p) => `## ${p.title}
|
|
991
|
+
|
|
992
|
+
Slug: ${p.slug}
|
|
993
|
+
|
|
994
|
+
${p.description}`).join("\n\n");
|
|
995
|
+
}
|
|
996
|
+
return { contents: [{ uri: "dataqueue://llms.txt", text: content }] };
|
|
997
|
+
});
|
|
998
|
+
server.tool(
|
|
999
|
+
"list-doc-pages",
|
|
1000
|
+
"List all available DataQueue documentation pages with titles and descriptions.",
|
|
1001
|
+
{},
|
|
1002
|
+
async () => {
|
|
1003
|
+
const listing = pages.map((p) => ({
|
|
1004
|
+
slug: p.slug,
|
|
1005
|
+
title: p.title,
|
|
1006
|
+
description: p.description
|
|
1007
|
+
}));
|
|
1008
|
+
return {
|
|
1009
|
+
content: [
|
|
1010
|
+
{ type: "text", text: JSON.stringify(listing, null, 2) }
|
|
1011
|
+
]
|
|
1012
|
+
};
|
|
1013
|
+
}
|
|
1014
|
+
);
|
|
1015
|
+
server.tool(
|
|
1016
|
+
"get-doc-page",
|
|
1017
|
+
"Fetch a specific DataQueue doc page by slug. Returns full page content as markdown.",
|
|
1018
|
+
{
|
|
1019
|
+
slug: zod.z.string().describe('The doc page slug, e.g. "usage/add-job" or "api/job-queue"')
|
|
1020
|
+
},
|
|
1021
|
+
async ({ slug }) => {
|
|
1022
|
+
const page = pages.find((p) => p.slug === slug);
|
|
1023
|
+
if (!page) {
|
|
1024
|
+
return {
|
|
1025
|
+
content: [
|
|
1026
|
+
{
|
|
1027
|
+
type: "text",
|
|
1028
|
+
text: `Page not found: "${slug}". Use list-doc-pages to see available slugs.`
|
|
1029
|
+
}
|
|
1030
|
+
],
|
|
1031
|
+
isError: true
|
|
1032
|
+
};
|
|
1033
|
+
}
|
|
1034
|
+
const header = page.description ? `# ${page.title}
|
|
1035
|
+
|
|
1036
|
+
> ${page.description}
|
|
1037
|
+
|
|
1038
|
+
` : `# ${page.title}
|
|
1039
|
+
|
|
1040
|
+
`;
|
|
1041
|
+
return {
|
|
1042
|
+
content: [{ type: "text", text: header + page.content }]
|
|
1043
|
+
};
|
|
1044
|
+
}
|
|
1045
|
+
);
|
|
1046
|
+
server.tool(
|
|
1047
|
+
"search-docs",
|
|
1048
|
+
"Full-text search across all DataQueue documentation pages. Returns matching sections with page titles and content excerpts.",
|
|
1049
|
+
{
|
|
1050
|
+
query: zod.z.string().describe('Search query, e.g. "cron scheduling" or "waitForToken"')
|
|
1051
|
+
},
|
|
1052
|
+
async ({ query }) => {
|
|
1053
|
+
const queryTerms = query.toLowerCase().split(/\s+/).filter((t) => t.length > 1);
|
|
1054
|
+
if (queryTerms.length === 0) {
|
|
1055
|
+
return {
|
|
1056
|
+
content: [
|
|
1057
|
+
{ type: "text", text: "Please provide a search query." }
|
|
1058
|
+
],
|
|
1059
|
+
isError: true
|
|
1060
|
+
};
|
|
1061
|
+
}
|
|
1062
|
+
const scored = pages.map((page) => ({
|
|
1063
|
+
page,
|
|
1064
|
+
score: scorePageForQuery(page, queryTerms)
|
|
1065
|
+
})).filter((r) => r.score > 0).sort((a, b) => b.score - a.score).slice(0, 5);
|
|
1066
|
+
if (scored.length === 0) {
|
|
1067
|
+
return {
|
|
1068
|
+
content: [
|
|
1069
|
+
{
|
|
1070
|
+
type: "text",
|
|
1071
|
+
text: `No results for "${query}". Try different keywords or use list-doc-pages to browse.`
|
|
1072
|
+
}
|
|
1073
|
+
]
|
|
1074
|
+
};
|
|
1075
|
+
}
|
|
1076
|
+
const results = scored.map((r) => {
|
|
1077
|
+
const excerpt = extractExcerpt(r.page.content, queryTerms);
|
|
1078
|
+
return `## ${r.page.title} (${r.page.slug})
|
|
1079
|
+
|
|
1080
|
+
${r.page.description}
|
|
1081
|
+
|
|
1082
|
+
${excerpt}`;
|
|
1083
|
+
});
|
|
1084
|
+
return {
|
|
1085
|
+
content: [{ type: "text", text: results.join("\n\n---\n\n") }]
|
|
1086
|
+
};
|
|
1087
|
+
}
|
|
1088
|
+
);
|
|
1089
|
+
const transport = deps.transport ?? new stdio_js.StdioServerTransport();
|
|
1090
|
+
await server.connect(transport);
|
|
1091
|
+
return server;
|
|
1092
|
+
}
|
|
1093
|
+
var isDirectRun = process.argv[1] && (process.argv[1].endsWith("/mcp-server.js") || process.argv[1].endsWith("/mcp-server.cjs"));
|
|
1094
|
+
if (isDirectRun) {
|
|
1095
|
+
startMcpServer().catch((err) => {
|
|
1096
|
+
console.error("Failed to start MCP server:", err);
|
|
1097
|
+
process.exit(1);
|
|
1098
|
+
});
|
|
1099
|
+
}
|
|
581
1100
|
|
|
582
1101
|
// src/cli.ts
|
|
583
|
-
var
|
|
584
|
-
var
|
|
1102
|
+
var __filename4 = url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli.cjs', document.baseURI).href)));
|
|
1103
|
+
var __dirname4 = path3__default.default.dirname(__filename4);
|
|
585
1104
|
function runCli(argv, {
|
|
586
1105
|
log = console.log,
|
|
587
1106
|
error = console.error,
|
|
588
1107
|
exit = (code) => process.exit(code),
|
|
589
1108
|
spawnSyncImpl = child_process.spawnSync,
|
|
590
|
-
migrationsDir =
|
|
1109
|
+
migrationsDir = path3__default.default.join(__dirname4, "../migrations"),
|
|
591
1110
|
initDeps,
|
|
592
|
-
runInitImpl = runInit
|
|
1111
|
+
runInitImpl = runInit,
|
|
1112
|
+
installSkillsDeps,
|
|
1113
|
+
runInstallSkillsImpl = runInstallSkills,
|
|
1114
|
+
installRulesDeps,
|
|
1115
|
+
runInstallRulesImpl = runInstallRules,
|
|
1116
|
+
installMcpDeps,
|
|
1117
|
+
runInstallMcpImpl = runInstallMcp,
|
|
1118
|
+
startMcpServerImpl = startMcpServer
|
|
593
1119
|
} = {}) {
|
|
594
1120
|
const [, , command, ...restArgs] = argv;
|
|
595
1121
|
function printUsage() {
|
|
@@ -598,6 +1124,10 @@ function runCli(argv, {
|
|
|
598
1124
|
" dataqueue-cli migrate [--envPath <path>] [-s <schema> | --schema <schema>]"
|
|
599
1125
|
);
|
|
600
1126
|
log(" dataqueue-cli init");
|
|
1127
|
+
log(" dataqueue-cli install-skills");
|
|
1128
|
+
log(" dataqueue-cli install-rules");
|
|
1129
|
+
log(" dataqueue-cli install-mcp");
|
|
1130
|
+
log(" dataqueue-cli mcp");
|
|
601
1131
|
log("");
|
|
602
1132
|
log("Options for migrate:");
|
|
603
1133
|
log(
|
|
@@ -607,24 +1137,13 @@ function runCli(argv, {
|
|
|
607
1137
|
" -s, --schema <schema> Set the schema to use (passed to node-pg-migrate)"
|
|
608
1138
|
);
|
|
609
1139
|
log("");
|
|
610
|
-
log("
|
|
611
|
-
log(
|
|
612
|
-
|
|
613
|
-
);
|
|
614
|
-
log(
|
|
615
|
-
" - For managed Postgres (e.g., DigitalOcean) with SSL, set PGSSLMODE=require and PGSSLROOTCERT to your CA .crt file."
|
|
616
|
-
);
|
|
617
|
-
log(
|
|
618
|
-
" Example: PGSSLMODE=require NODE_EXTRA_CA_CERTS=/absolute/path/to/ca.crt PG_DATAQUEUE_DATABASE=... npx dataqueue-cli migrate"
|
|
619
|
-
);
|
|
620
|
-
log("");
|
|
621
|
-
log("Notes for init:");
|
|
622
|
-
log(
|
|
623
|
-
" - Supports both Next.js App Router and Pages Router (prefers App Router if both exist)."
|
|
624
|
-
);
|
|
1140
|
+
log("AI tooling commands:");
|
|
1141
|
+
log(" install-skills Install DataQueue skill files for AI assistants");
|
|
1142
|
+
log(" install-rules Install DataQueue agent rules for AI clients");
|
|
625
1143
|
log(
|
|
626
|
-
" -
|
|
1144
|
+
" install-mcp Configure the DataQueue MCP server for AI clients"
|
|
627
1145
|
);
|
|
1146
|
+
log(" mcp Start the DataQueue MCP server (stdio)");
|
|
628
1147
|
exit(1);
|
|
629
1148
|
}
|
|
630
1149
|
if (command === "migrate") {
|
|
@@ -668,6 +1187,32 @@ function runCli(argv, {
|
|
|
668
1187
|
exit,
|
|
669
1188
|
...initDeps
|
|
670
1189
|
});
|
|
1190
|
+
} else if (command === "install-skills") {
|
|
1191
|
+
runInstallSkillsImpl({
|
|
1192
|
+
log,
|
|
1193
|
+
error,
|
|
1194
|
+
exit,
|
|
1195
|
+
...installSkillsDeps
|
|
1196
|
+
});
|
|
1197
|
+
} else if (command === "install-rules") {
|
|
1198
|
+
runInstallRulesImpl({
|
|
1199
|
+
log,
|
|
1200
|
+
error,
|
|
1201
|
+
exit,
|
|
1202
|
+
...installRulesDeps
|
|
1203
|
+
});
|
|
1204
|
+
} else if (command === "install-mcp") {
|
|
1205
|
+
runInstallMcpImpl({
|
|
1206
|
+
log,
|
|
1207
|
+
error,
|
|
1208
|
+
exit,
|
|
1209
|
+
...installMcpDeps
|
|
1210
|
+
});
|
|
1211
|
+
} else if (command === "mcp") {
|
|
1212
|
+
startMcpServerImpl().catch((err) => {
|
|
1213
|
+
error("Failed to start MCP server:", err);
|
|
1214
|
+
exit(1);
|
|
1215
|
+
});
|
|
671
1216
|
} else {
|
|
672
1217
|
printUsage();
|
|
673
1218
|
}
|