create-thally-docs 0.7.9 → 0.8.1

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/README.md CHANGED
@@ -1,8 +1,10 @@
1
1
  # create-thally-docs
2
2
 
3
- Scaffold a new [Thally](https://github.com/thallylabs/thally) documentation project an
4
- agent-native docs site that serves every page to humans as polished HTML and to
5
- AI agents as structured JSON, JSON-LD, and Markdown from the same URL.
3
+ Scaffold the first customer-facing knowledge surface in a
4
+ [Thally](https://github.com/thallylabs/thally) product-knowledge pipeline. The
5
+ result is an open documentation site that serves every page to humans as
6
+ polished HTML and to agents as structured JSON, JSON-LD, and Markdown from the
7
+ same URL.
6
8
 
7
9
  ## Quick start
8
10
 
@@ -44,6 +46,16 @@ interactive question explicitly.
44
46
  | `create-thally-docs check [dir] [--fix]` | Lint content for orphan pages and missing frontmatter |
45
47
  | `create-thally-docs translate --locale <code>` | Translate content into another locale |
46
48
 
49
+ Interactive migrations ask whether the source is Mintlify, Docusaurus, or
50
+ another auto-detected platform. When automatic detection receives a live
51
+ website URL, the CLI recommends its source GitHub repository and requires
52
+ confirmation before continuing with the less precise website crawl. For
53
+ scripts and CI, pass
54
+ `--platform mintlify`, `--platform docusaurus`, or `--platform auto`; `--yes`
55
+ keeps backward-compatible auto-detection when no platform flag is supplied.
56
+ Explicit `--platform auto` and `--yes` runs print the live-site limitation
57
+ without introducing an interactive prompt.
58
+
47
59
  Prefer a single binary? Install [`@thallylabs/cli`](https://www.npmjs.com/package/@thallylabs/cli)
48
60
  and use `thally init`, which delegates here.
49
61
 
@@ -23,6 +23,8 @@ var EXCLUDE_PATHS = [
23
23
  "/.next/",
24
24
  "/.data/",
25
25
  "/.thally/",
26
+ // The first-party docs deployment pins its own canonical origin.
27
+ "/.env.production",
26
28
  "/thally-track.yml",
27
29
  "/CODEOWNERS",
28
30
  "/CLAUDE.md",
@@ -3,7 +3,7 @@ import {
3
3
  initGit,
4
4
  installDeps,
5
5
  scaffold
6
- } from "./chunk-5GIGIHI5.js";
6
+ } from "./chunk-RS6U2GSX.js";
7
7
 
8
8
  // src/migrate/index.ts
9
9
  import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "fs";
@@ -41,7 +41,12 @@ async function discoverMigration(options) {
41
41
  const url = new URL(options.sourceUrl);
42
42
  if (url.hostname.toLowerCase() !== "github.com") {
43
43
  console.log(` \u{1F310} Discovering public docs at ${url.origin}${url.pathname}...`);
44
- return migrateUrl({ sourceUrl: options.sourceUrl, maxPages: options.maxPages, fetcher: options.fetcher });
44
+ return migrateUrl({
45
+ sourceUrl: options.sourceUrl,
46
+ platform: options.platform,
47
+ maxPages: options.maxPages,
48
+ fetcher: options.fetcher
49
+ });
45
50
  }
46
51
  const source = parseGitHubRepositoryUrl(options.sourceUrl);
47
52
  if (options.branch) source.branch = options.branch;
@@ -53,7 +58,8 @@ async function discoverMigration(options) {
53
58
  return migrateRepository({
54
59
  repositoryDir: cloneDir,
55
60
  sourceUrl: options.sourceUrl,
56
- docsDir: options.docsDir ?? (source.docsDir || void 0)
61
+ docsDir: options.docsDir ?? (source.docsDir || void 0),
62
+ platform: options.platform
57
63
  });
58
64
  } finally {
59
65
  rmSync(temporaryRoot, { recursive: true, force: true });
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  migrateDocs
4
- } from "./chunk-Y2JKKZ4I.js";
4
+ } from "./chunk-SDZZYPSN.js";
5
5
  import {
6
6
  logo,
7
7
  readDocsJson,
@@ -9,16 +9,84 @@ import {
9
9
  slugify,
10
10
  success,
11
11
  writeDocsJson
12
- } from "./chunk-5GIGIHI5.js";
12
+ } from "./chunk-RS6U2GSX.js";
13
13
 
14
14
  // src/index.ts
15
15
  import { existsSync as existsSync3, readdirSync as readdirSync2 } from "fs";
16
16
  import { resolve as resolve2 } from "path";
17
17
 
18
18
  // src/prompts.ts
19
- import { input, select } from "@inquirer/prompts";
20
- import { basename } from "path";
21
- import { resolve } from "path";
19
+ import { confirm, input, select } from "@inquirer/prompts";
20
+ import { basename, resolve } from "path";
21
+ import {
22
+ parseGitHubRepositoryUrl
23
+ } from "@thallylabs/migrate";
24
+ function parseMigrationPlatform(value) {
25
+ if (!value || value === "auto") return void 0;
26
+ if (value === "mintlify" || value === "docusaurus") return value;
27
+ throw new Error("--platform must be mintlify, docusaurus, or auto.");
28
+ }
29
+ async function gatherMigrationPlatform(value, useDefaults) {
30
+ const configured = parseMigrationPlatform(value);
31
+ if (configured || value === "auto" || useDefaults) return configured;
32
+ return select({
33
+ message: " Which platform currently hosts these docs?",
34
+ choices: [
35
+ { name: "Mintlify", value: "mintlify" },
36
+ { name: "Docusaurus", value: "docusaurus" },
37
+ { name: "Other / detect automatically", value: void 0 }
38
+ ],
39
+ default: "mintlify"
40
+ });
41
+ }
42
+ var LIVE_URL_MIGRATION_WARNING = "Live website migration reconstructs documentation from public output and may need manual alignment. A source GitHub repository produces a more accurate migration. Use the Thally MCP afterward if the generated project needs refinement.";
43
+ function validateGitHubRepositorySource(value) {
44
+ try {
45
+ parseGitHubRepositoryUrl(value);
46
+ return true;
47
+ } catch (error) {
48
+ return error instanceof Error ? error.message : "Enter a valid public GitHub repository URL.";
49
+ }
50
+ }
51
+ async function resolveAutoDetectedMigrationSource(sourceUrl, shouldPrompt) {
52
+ const source = new URL(sourceUrl);
53
+ if (source.hostname.toLowerCase() === "github.com") return sourceUrl;
54
+ console.warn(`
55
+ \u26A0 ${LIVE_URL_MIGRATION_WARNING}`);
56
+ if (!shouldPrompt) return sourceUrl;
57
+ const sourcePreference = await select({
58
+ message: " Which source should Thally migrate?",
59
+ choices: [
60
+ {
61
+ name: "Source GitHub repository (recommended)",
62
+ value: "github"
63
+ },
64
+ {
65
+ name: "Continue with the live website URL",
66
+ value: "website"
67
+ }
68
+ ],
69
+ default: "github"
70
+ });
71
+ if (sourcePreference === "github") {
72
+ const repositoryUrl = await input({
73
+ message: " GitHub repository URL:",
74
+ validate: validateGitHubRepositorySource
75
+ });
76
+ parseGitHubRepositoryUrl(repositoryUrl);
77
+ return repositoryUrl;
78
+ }
79
+ const hasAcceptedAlignment = await confirm({
80
+ message: " Continue knowing the migration may need manual alignment, using the Thally MCP afterward if needed?",
81
+ default: false
82
+ });
83
+ if (!hasAcceptedAlignment) {
84
+ throw new Error(
85
+ "Migration cancelled. Re-run with the source GitHub repository for the most accurate result."
86
+ );
87
+ }
88
+ return sourceUrl;
89
+ }
22
90
  async function gatherAnswers(dirArg, useDefaults, installPreference) {
23
91
  let projectDir;
24
92
  if (dirArg) {
@@ -114,13 +182,26 @@ async function gatherAnswers(dirArg, useDefaults, installPreference) {
114
182
  }
115
183
 
116
184
  // src/index.ts
117
- import { parseGitHubRepositoryUrl } from "@thallylabs/migrate";
185
+ import { parseGitHubRepositoryUrl as parseGitHubRepositoryUrl2 } from "@thallylabs/migrate";
118
186
 
119
187
  // src/check.ts
120
188
  import { existsSync, readFileSync, readdirSync, statSync } from "fs";
121
189
  import { join, extname, relative } from "path";
122
190
  import { execFileSync } from "child_process";
191
+
192
+ // src/frontmatter.ts
123
193
  import matter from "gray-matter";
194
+ var FRONTMATTER_OPTIONS = {
195
+ engines: {
196
+ javascript: () => ({}),
197
+ js: () => ({})
198
+ }
199
+ };
200
+ function parseFrontmatter(raw) {
201
+ return matter(raw, FRONTMATTER_OPTIONS);
202
+ }
203
+
204
+ // src/check.ts
124
205
  import { parse as parseYaml } from "yaml";
125
206
  function gitLocal(projectDir, args2) {
126
207
  try {
@@ -356,7 +437,7 @@ async function runCheck(projectDir, options) {
356
437
  let lineOffset = 0;
357
438
  try {
358
439
  const raw = readFileSync(filePath, "utf8");
359
- const parsed = matter(raw);
440
+ const parsed = parseFrontmatter(raw);
360
441
  data = parsed.data;
361
442
  content = parsed.content;
362
443
  lineOffset = raw.slice(0, raw.indexOf(content)).split("\n").length - 1;
@@ -457,7 +538,6 @@ thally check: ${errors.length} error(s), ${warnings.length} warning(s)`);
457
538
  import { readFileSync as readFileSync2, writeFileSync, existsSync as existsSync2, mkdirSync } from "fs";
458
539
  import { join as join2, dirname } from "path";
459
540
  import { input as input2 } from "@inquirer/prompts";
460
- import matter2 from "gray-matter";
461
541
  import Anthropic from "@anthropic-ai/sdk";
462
542
  import pLimit from "p-limit";
463
543
  function readDocsJson2(projectDir) {
@@ -637,11 +717,11 @@ async function runTranslateCommand(locale, pages, force, apiKey, model, yes, pro
637
717
  }
638
718
  console.log("");
639
719
  if (!yes) {
640
- const confirm = await input2({
720
+ const confirm2 = await input2({
641
721
  message: " Proceed? (Y/n):",
642
722
  default: "Y"
643
723
  });
644
- if (confirm.toLowerCase() === "n") {
724
+ if (confirm2.toLowerCase() === "n") {
645
725
  console.log("\n Aborted.");
646
726
  return;
647
727
  }
@@ -655,7 +735,7 @@ async function runTranslateCommand(locale, pages, force, apiKey, model, yes, pro
655
735
  ({ pageId, sourceFile, targetFile }) => limit(async () => {
656
736
  try {
657
737
  const sourceContent = readFileSync2(sourceFile, "utf8");
658
- const parsed = matter2(sourceContent);
738
+ const parsed = parseFrontmatter(sourceContent);
659
739
  if (!parsed.data.title) {
660
740
  console.warn(` \u26A0 ${pageId}: missing title in frontmatter \u2014 translating anyway`);
661
741
  }
@@ -692,8 +772,10 @@ var valueFlags = /* @__PURE__ */ new Set([
692
772
  "--docs-dir",
693
773
  "--into",
694
774
  "--locale",
775
+ "--max-pages",
695
776
  "--model",
696
- "--pages"
777
+ "--pages",
778
+ "--platform"
697
779
  ]);
698
780
  var positional = [];
699
781
  for (let i = 0; i < args.length; i++) {
@@ -713,7 +795,7 @@ function getFlagValue(flag) {
713
795
  return void 0;
714
796
  }
715
797
  async function runMigrateCommand() {
716
- const sourceUrl = positional[1];
798
+ let sourceUrl = positional[1];
717
799
  if (!sourceUrl) {
718
800
  console.error("\n \u274C Source URL is required.");
719
801
  console.error(" Usage: create-thally-docs migrate <github-or-docs-url> [output-dir] [options]");
@@ -724,12 +806,22 @@ async function runMigrateCommand() {
724
806
  try {
725
807
  source = new URL(sourceUrl);
726
808
  if (!["http:", "https:"].includes(source.protocol)) throw new Error("Only HTTP and HTTPS sources are supported.");
727
- if (source.hostname.toLowerCase() === "github.com") parseGitHubRepositoryUrl(sourceUrl);
809
+ if (source.hostname.toLowerCase() === "github.com") parseGitHubRepositoryUrl2(sourceUrl);
728
810
  } catch (err) {
729
811
  console.error(`
730
812
  \u274C ${err instanceof Error ? err.message : err}`);
731
813
  process.exit(1);
732
814
  }
815
+ const branch = getFlagValue("--branch");
816
+ const docsDir = getFlagValue("--docs-dir");
817
+ const yes = flags.includes("--yes") || flags.includes("-y");
818
+ const platformFlag = getFlagValue("--platform");
819
+ const platform = await gatherMigrationPlatform(platformFlag, yes);
820
+ if (platform === void 0) {
821
+ const shouldPromptForSource = platformFlag === void 0 && !yes;
822
+ sourceUrl = await resolveAutoDetectedMigrationSource(sourceUrl, shouldPromptForSource);
823
+ source = new URL(sourceUrl);
824
+ }
733
825
  const apiKey = getFlagValue("--api-key") ?? process.env.ANTHROPIC_API_KEY;
734
826
  const intoDir = getFlagValue("--into");
735
827
  const isInto = Boolean(intoDir);
@@ -739,18 +831,15 @@ async function runMigrateCommand() {
739
831
  } else if (positional[2]) {
740
832
  projectDir = resolve2(positional[2]);
741
833
  } else {
742
- const sourceName = source.hostname.toLowerCase() === "github.com" ? parseGitHubRepositoryUrl(sourceUrl).repo : source.pathname.split("/").filter(Boolean).at(-1) ?? source.hostname.split(".")[0];
834
+ const sourceName = source.hostname.toLowerCase() === "github.com" ? parseGitHubRepositoryUrl2(sourceUrl).repo : source.pathname.split("/").filter(Boolean).at(-1) ?? source.hostname.split(".")[0];
743
835
  projectDir = resolve2(`${slugify(sourceName)}-docs`);
744
836
  }
745
- const branch = getFlagValue("--branch");
746
- const docsDir = getFlagValue("--docs-dir");
747
837
  const maxPagesValue = getFlagValue("--max-pages");
748
838
  const maxPages = maxPagesValue ? Number(maxPagesValue) : void 0;
749
839
  if (maxPages !== void 0 && (!Number.isInteger(maxPages) || maxPages < 1 || maxPages > 1e3)) {
750
840
  console.error("\n \u274C --max-pages must be an integer between 1 and 1000.");
751
841
  process.exit(1);
752
842
  }
753
- const yes = flags.includes("--yes") || flags.includes("-y");
754
843
  logo();
755
844
  console.log(" \u{1F680} Thally Migrate");
756
845
  console.log("");
@@ -758,6 +847,7 @@ async function runMigrateCommand() {
758
847
  console.log(` Target: ${projectDir}`);
759
848
  if (branch) console.log(` Branch: ${branch}`);
760
849
  if (docsDir) console.log(` Docs dir: ${docsDir}`);
850
+ console.log(` Platform: ${platform ?? "auto-detect"}`);
761
851
  console.log("");
762
852
  await migrateDocs({
763
853
  sourceUrl,
@@ -767,6 +857,7 @@ async function runMigrateCommand() {
767
857
  branch,
768
858
  docsDir,
769
859
  maxPages,
860
+ platform,
770
861
  yes
771
862
  });
772
863
  }
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  migrateDocs
4
- } from "../chunk-Y2JKKZ4I.js";
5
- import "../chunk-5GIGIHI5.js";
4
+ } from "../chunk-SDZZYPSN.js";
5
+ import "../chunk-RS6U2GSX.js";
6
6
  export {
7
7
  migrateDocs
8
8
  };
package/dist/scaffold.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  scaffold
4
- } from "./chunk-5GIGIHI5.js";
4
+ } from "./chunk-RS6U2GSX.js";
5
5
  export {
6
6
  scaffold
7
7
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "create-thally-docs",
3
- "version": "0.7.9",
4
- "description": "Scaffold a new Thally documentation project",
3
+ "version": "0.8.1",
4
+ "description": "Scaffold the first documentation surface in a Thally product-knowledge pipeline.",
5
5
  "type": "module",
6
6
  "engines": {
7
7
  "node": ">=18"
@@ -28,7 +28,7 @@
28
28
  "dependencies": {
29
29
  "@anthropic-ai/sdk": "^0.36.0",
30
30
  "@inquirer/prompts": "^7.0.0",
31
- "@thallylabs/migrate": "0.1.2",
31
+ "@thallylabs/migrate": "0.2.0",
32
32
  "gray-matter": "^4.0.3",
33
33
  "p-limit": "^6.1.0",
34
34
  "tar": "^6.2.0",