@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/dist/cli.cjs CHANGED
@@ -1,14 +1,20 @@
1
1
  'use strict';
2
2
 
3
3
  var child_process = require('child_process');
4
- var path = require('path');
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 path__default = /*#__PURE__*/_interopDefault(path);
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 = path__default.default.join(cwd, "package.json");
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 = path__default.default.join(cwd, "src");
395
+ const srcDir = path3__default.default.join(cwd, "src");
390
396
  const srcRoot = existsSyncImpl(srcDir) ? "src" : ".";
391
- const appDir = path__default.default.join(cwd, srcRoot, "app");
392
- const pagesDir = path__default.default.join(cwd, srcRoot, "pages");
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 = path__default.default.join(
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 = path__default.default.join(
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 = path__default.default.join(
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 = path__default.default.join(details.cwd, "cron.sh");
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(path__default.default.dirname(absolutePath), { recursive: true });
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 = path__default.default.relative(cwd, absolutePath);
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 __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)));
584
- var __dirname$1 = path__default.default.dirname(__filename$1);
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 = path__default.default.join(__dirname$1, "../migrations"),
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("Notes:");
611
- log(
612
- " - The PG_DATAQUEUE_DATABASE environment variable must be set to your Postgres connection string."
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
- " - Scaffolds endpoint, cron.sh, queue placeholder, and package.json entries."
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
  }