@treeseed/sdk 0.6.50 → 0.7.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/index.d.ts +3 -2
- package/dist/index.js +21 -5
- package/dist/operations/providers/default.js +453 -5
- package/dist/operations/runtime.js +1 -0
- package/dist/operations/services/github-automation.d.ts +3 -1
- package/dist/operations/services/github-automation.js +2 -2
- package/dist/operations/services/hub-launch.d.ts +182 -0
- package/dist/operations/services/hub-launch.js +308 -0
- package/dist/operations/services/{knowledge-coop-launch.d.ts → hub-provider-launch.d.ts} +47 -17
- package/dist/operations/services/{knowledge-coop-launch.js → hub-provider-launch.js} +144 -41
- package/dist/operations/services/project-platform.js +5 -1
- package/dist/operations/services/railway-deploy.d.ts +2 -2
- package/dist/operations/services/railway-deploy.js +27 -3
- package/dist/operations-registry.js +15 -0
- package/dist/operations-types.d.ts +1 -0
- package/dist/operations.d.ts +2 -0
- package/dist/operations.js +17 -1
- package/dist/remote.d.ts +11 -0
- package/dist/remote.js +6 -0
- package/dist/workflow/operations.js +34 -27
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
1
|
+
import { cpSync, mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync, existsSync } from "node:fs";
|
|
2
2
|
import { spawnSync } from "node:child_process";
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
4
|
import { dirname, join, resolve } from "node:path";
|
|
@@ -18,12 +18,12 @@ import { templateCatalogRoot } from "./runtime-paths.js";
|
|
|
18
18
|
import { scaffoldTemplateProject } from "./template-registry.js";
|
|
19
19
|
import { buildKnowledgeCoopKnowledgePackPackage, buildKnowledgeCoopTemplatePackage, importKnowledgeCoopKnowledgePack } from "./knowledge-coop-packaging.js";
|
|
20
20
|
import { resolveTreeseedToolBinary } from "../../managed-dependencies.js";
|
|
21
|
-
class
|
|
21
|
+
class KnowledgeHubProviderLaunchError extends Error {
|
|
22
22
|
phase;
|
|
23
23
|
phases;
|
|
24
24
|
constructor(phase, message, phases = []) {
|
|
25
25
|
super(message);
|
|
26
|
-
this.name = "
|
|
26
|
+
this.name = "KnowledgeHubProviderLaunchError";
|
|
27
27
|
this.phase = phase;
|
|
28
28
|
this.phases = [...phases];
|
|
29
29
|
}
|
|
@@ -132,13 +132,13 @@ The first release should verify that the hub is live, the core direction is visi
|
|
|
132
132
|
`);
|
|
133
133
|
writeText(resolve(projectRoot, "src/content/notes", `${noteSlug}.mdx`), `---
|
|
134
134
|
title: ${input.projectName} Operating Model
|
|
135
|
-
description: The initial working agreements for this Knowledge
|
|
135
|
+
description: The initial working agreements for this Knowledge Hub.
|
|
136
136
|
date: ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}
|
|
137
137
|
summary: Managed launch created the default branches, runtime wiring, and first operational checkpoints.
|
|
138
138
|
status: live
|
|
139
139
|
---
|
|
140
140
|
|
|
141
|
-
This hub starts with a
|
|
141
|
+
This hub starts with a Knowledge Hub launch, a seeded objective, and a visible first workstream so the team can continue from a known baseline.
|
|
142
142
|
`);
|
|
143
143
|
writeText(resolve(projectRoot, "src/content/proposals", "establish-initial-operating-routine.mdx"), `---
|
|
144
144
|
id: ${proposalId}
|
|
@@ -166,11 +166,11 @@ id: ${decisionId}
|
|
|
166
166
|
title: Adopt The Initial Launch Posture
|
|
167
167
|
description: Record the launch decision for the first operating cycle of the hub.
|
|
168
168
|
date: ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}
|
|
169
|
-
summary: The
|
|
169
|
+
summary: The Knowledge Hub launch will begin with a narrow first release and explicit direction artifacts.
|
|
170
170
|
status: live
|
|
171
171
|
decisionType: approved
|
|
172
172
|
rationale: The initial launch should bias toward clarity, setup completion, and a visible first release loop.
|
|
173
|
-
authority: Knowledge
|
|
173
|
+
authority: Knowledge Hub launch
|
|
174
174
|
primaryContributor: ${stewardSlug}
|
|
175
175
|
relatedObjectives:
|
|
176
176
|
- launch-knowledge-hub
|
|
@@ -514,13 +514,15 @@ function commandAvailable(command) {
|
|
|
514
514
|
}
|
|
515
515
|
return spawnSync("bash", ["-lc", `command -v ${command}`], { stdio: "ignore" }).status === 0;
|
|
516
516
|
}
|
|
517
|
-
function appendPhase(phases, phase, status, detail) {
|
|
518
|
-
|
|
517
|
+
async function appendPhase(phases, phase, status, detail, reporter) {
|
|
518
|
+
const record = {
|
|
519
519
|
phase,
|
|
520
520
|
status,
|
|
521
521
|
detail,
|
|
522
522
|
timestamp: nowIso()
|
|
523
|
-
}
|
|
523
|
+
};
|
|
524
|
+
phases.push(record);
|
|
525
|
+
await reporter?.(record);
|
|
524
526
|
}
|
|
525
527
|
function stringValue(value) {
|
|
526
528
|
return typeof value === "string" && value.trim().length > 0 ? value.trim() : "";
|
|
@@ -565,6 +567,7 @@ function buildProcessingHostEnvironmentOverlay(input, scope) {
|
|
|
565
567
|
return overlay;
|
|
566
568
|
}
|
|
567
569
|
function scaffoldKnowledgeCoopSource(projectRoot, input) {
|
|
570
|
+
const repositoryName = slugify(input.repoName ?? input.projectSlug, "project");
|
|
568
571
|
const templateId = input.sourceKind === "template" ? slugify(input.sourceRef ?? "starter-basic", "starter-basic") : "starter-basic";
|
|
569
572
|
const templateCatalogEnv = { TREESEED_TEMPLATE_CATALOG_URL: currentTemplateCatalogUrl() };
|
|
570
573
|
if (input.sourceKind === "knowledge_pack") {
|
|
@@ -590,13 +593,59 @@ function scaffoldKnowledgeCoopSource(projectRoot, input) {
|
|
|
590
593
|
slug: input.projectSlug,
|
|
591
594
|
siteUrl: resolveManagedWebUrl(slugify(input.projectSlug, "project")),
|
|
592
595
|
contactEmail: input.contactEmail ?? `hello+${slugify(input.projectSlug, "project")}@knowledge.coop`,
|
|
593
|
-
repositoryUrl: `https://github.com/${slugify(input.repoOwner ?? resolveDefaultGitHubOwner(), "treeseed-ai")}/${
|
|
596
|
+
repositoryUrl: `https://github.com/${slugify(input.repoOwner ?? resolveDefaultGitHubOwner(), "treeseed-ai")}/${repositoryName}`
|
|
594
597
|
}, {
|
|
595
598
|
cwd: projectRoot,
|
|
596
599
|
env: templateCatalogEnv
|
|
597
600
|
});
|
|
598
601
|
}
|
|
599
|
-
|
|
602
|
+
function repositoryHostGitHubEnvOverlay() {
|
|
603
|
+
const token = process.env.TREESEED_HOSTED_HUBS_GITHUB_TOKEN || process.env.TREESEED_REPOSITORY_HOST_GITHUB_TOKEN || process.env.GH_TOKEN || process.env.GITHUB_TOKEN || "";
|
|
604
|
+
return token ? { ...process.env, GH_TOKEN: token, GITHUB_TOKEN: token } : process.env;
|
|
605
|
+
}
|
|
606
|
+
function prepareKnowledgeHubContentRepositoryRoot(sourceRoot, contentRoot, input) {
|
|
607
|
+
mkdirSync(contentRoot, { recursive: true });
|
|
608
|
+
const contentSource = resolve(sourceRoot, "src", "content");
|
|
609
|
+
if (existsSync(contentSource)) {
|
|
610
|
+
cpSync(contentSource, resolve(contentRoot, "src", "content"), { recursive: true });
|
|
611
|
+
}
|
|
612
|
+
const publicSource = resolve(sourceRoot, "public");
|
|
613
|
+
if (existsSync(publicSource)) {
|
|
614
|
+
cpSync(publicSource, resolve(contentRoot, "public"), { recursive: true });
|
|
615
|
+
}
|
|
616
|
+
writeFileSync(resolve(contentRoot, "README.md"), `# ${input.projectName} Content
|
|
617
|
+
|
|
618
|
+
Content source for the ${input.projectName} TreeSeed Knowledge Hub.
|
|
619
|
+
`, "utf8");
|
|
620
|
+
writeFileSync(resolve(contentRoot, "treeseed.content.json"), `${JSON.stringify({
|
|
621
|
+
schemaVersion: 1,
|
|
622
|
+
kind: "treeseed_hub_content",
|
|
623
|
+
projectId: input.projectId,
|
|
624
|
+
projectSlug: input.projectSlug,
|
|
625
|
+
contentRoot: "src/content",
|
|
626
|
+
productionSource: "r2_published_artifacts",
|
|
627
|
+
overlayPolicy: "src_content_when_present"
|
|
628
|
+
}, null, 2)}
|
|
629
|
+
`, "utf8");
|
|
630
|
+
}
|
|
631
|
+
function stripSoftwareContentOverlay(sourceRoot, input) {
|
|
632
|
+
const contentRoot = resolve(sourceRoot, "src", "content");
|
|
633
|
+
rmSync(contentRoot, { recursive: true, force: true });
|
|
634
|
+
mkdirSync(contentRoot, { recursive: true });
|
|
635
|
+
writeFileSync(resolve(contentRoot, ".gitkeep"), "", "utf8");
|
|
636
|
+
writeFileSync(
|
|
637
|
+
resolve(contentRoot, "README.md"),
|
|
638
|
+
`# Preview content overlay
|
|
639
|
+
|
|
640
|
+
This software repository does not own ordinary Knowledge Hub content. Production content is published from the content repository to R2 artifacts. Checked-out files under \`src/content\` are for local, staging, or preview overlays only.
|
|
641
|
+
|
|
642
|
+
Hub: ${input.projectName}
|
|
643
|
+
Content source: ${input.contentRepository?.name ?? `${slugify(input.projectSlug, "project")}-content`}
|
|
644
|
+
`,
|
|
645
|
+
"utf8"
|
|
646
|
+
);
|
|
647
|
+
}
|
|
648
|
+
async function validateKnowledgeHubProviderLaunchPrerequisites(tenantRoot = process.cwd(), { valuesOverlay = {} } = {}) {
|
|
600
649
|
const values = collectTreeseedConfigSeedValues(tenantRoot, "prod", process.env, valuesOverlay);
|
|
601
650
|
const requiredConfig = [
|
|
602
651
|
["TREESEED_BETTER_AUTH_SECRET"],
|
|
@@ -628,8 +677,9 @@ async function validateKnowledgeCoopManagedLaunchPrerequisites(tenantRoot = proc
|
|
|
628
677
|
commands
|
|
629
678
|
};
|
|
630
679
|
}
|
|
631
|
-
async function
|
|
680
|
+
async function executeKnowledgeHubProviderLaunch(input, options = {}) {
|
|
632
681
|
const phases = [];
|
|
682
|
+
const reportPhase = options.onPhase;
|
|
633
683
|
const prodEnvOverlay = {
|
|
634
684
|
...buildCloudflareHostEnvironmentOverlay(input, "prod"),
|
|
635
685
|
...buildProcessingHostEnvironmentOverlay(input, "prod")
|
|
@@ -638,35 +688,82 @@ async function executeKnowledgeCoopManagedLaunch(input) {
|
|
|
638
688
|
...buildCloudflareHostEnvironmentOverlay(input, "staging"),
|
|
639
689
|
...buildProcessingHostEnvironmentOverlay(input, "staging")
|
|
640
690
|
};
|
|
641
|
-
const preflight = await
|
|
691
|
+
const preflight = await validateKnowledgeHubProviderLaunchPrerequisites(process.cwd(), { valuesOverlay: prodEnvOverlay });
|
|
642
692
|
if (!preflight.ok) {
|
|
643
|
-
throw new
|
|
693
|
+
throw new KnowledgeHubProviderLaunchError(
|
|
644
694
|
"runtime_connection_failed",
|
|
645
|
-
`Knowledge
|
|
695
|
+
`Knowledge Hub launch preflight failed: ${[...preflight.missingConfig, ...preflight.providerChecks.issues].join("; ") || "provider checks failed."}`,
|
|
646
696
|
[]
|
|
647
697
|
);
|
|
648
698
|
}
|
|
649
|
-
const workingRoot = mkdtempSync(join(tmpdir(), `
|
|
699
|
+
const workingRoot = mkdtempSync(join(tmpdir(), `hub-provider-launch-${slugify(input.projectSlug, "project")}-`));
|
|
650
700
|
const repoOwner = slugify(input.repoOwner ?? resolveDefaultGitHubOwner(), "treeseed-ai");
|
|
651
|
-
const repoName = slugify(input.projectSlug, "project");
|
|
701
|
+
const repoName = slugify(input.repoName ?? input.projectSlug, "project");
|
|
702
|
+
const githubEnv = repositoryHostGitHubEnvOverlay();
|
|
703
|
+
let packageSourceRoot = null;
|
|
652
704
|
try {
|
|
653
|
-
appendPhase(phases, "repo_provision", "running", "Creating GitHub repository.");
|
|
654
|
-
const repository =
|
|
705
|
+
await appendPhase(phases, "repo_provision", "running", "Creating or connecting GitHub software repository.", reportPhase);
|
|
706
|
+
const repository = input.existingRepository?.url ? {
|
|
707
|
+
slug: `${input.existingRepository.owner}/${input.existingRepository.name}`,
|
|
708
|
+
owner: input.existingRepository.owner,
|
|
709
|
+
name: input.existingRepository.name,
|
|
710
|
+
url: input.existingRepository.url,
|
|
711
|
+
visibility: input.existingRepository.visibility ?? input.repoVisibility ?? "private"
|
|
712
|
+
} : await createGitHubRepository({
|
|
655
713
|
owner: repoOwner,
|
|
656
714
|
name: repoName,
|
|
657
|
-
description: input.summary ?? `Knowledge
|
|
715
|
+
description: input.summary ?? `Knowledge Hub for ${input.projectName}`,
|
|
658
716
|
visibility: input.repoVisibility ?? "private",
|
|
659
717
|
homepageUrl: resolveManagedWebUrl(repoName),
|
|
660
718
|
topics: ["knowledge-coop", "treeseed", "knowledge-hub"]
|
|
661
|
-
});
|
|
662
|
-
appendPhase(phases, "repo_provision", "completed",
|
|
663
|
-
appendPhase(phases, "content_bootstrap", "running", "Scaffolding the project and seeding initial content.");
|
|
719
|
+
}, { env: githubEnv });
|
|
720
|
+
await appendPhase(phases, "repo_provision", "completed", `${input.existingRepository?.url ? "Connected" : "Created"} ${repository.slug}.`, reportPhase);
|
|
721
|
+
await appendPhase(phases, "content_bootstrap", "running", "Scaffolding the project and seeding initial content.", reportPhase);
|
|
664
722
|
await scaffoldKnowledgeCoopSource(workingRoot, input);
|
|
665
723
|
ensureHostedProjectFiles(workingRoot);
|
|
666
724
|
const managedDefaults = applyManagedProjectDefaults(workingRoot, input);
|
|
667
725
|
const seed = seedKnowledgeCoopContent(workingRoot, input);
|
|
668
|
-
|
|
669
|
-
|
|
726
|
+
packageSourceRoot = mkdtempSync(join(tmpdir(), `knowledge-coop-package-${slugify(input.projectSlug, "project")}-`));
|
|
727
|
+
cpSync(workingRoot, packageSourceRoot, { recursive: true });
|
|
728
|
+
await appendPhase(phases, "content_bootstrap", "completed", "Scaffolded the repo and seeded Direct content.", reportPhase);
|
|
729
|
+
let contentRepository = null;
|
|
730
|
+
let contentRepositoryWorkingRoot = null;
|
|
731
|
+
if (input.contentRepository?.name) {
|
|
732
|
+
await appendPhase(phases, "content_repository", "running", "Creating content repository.", reportPhase);
|
|
733
|
+
contentRepositoryWorkingRoot = mkdtempSync(join(tmpdir(), `knowledge-coop-content-${slugify(input.projectSlug, "project")}-`));
|
|
734
|
+
prepareKnowledgeHubContentRepositoryRoot(workingRoot, contentRepositoryWorkingRoot, input);
|
|
735
|
+
const createdContentRepository = input.contentRepository.url ? {
|
|
736
|
+
slug: `${slugify(input.contentRepository.owner ?? repoOwner, "treeseed-ai")}/${slugify(input.contentRepository.name, `${repoName}-content`)}`,
|
|
737
|
+
owner: slugify(input.contentRepository.owner ?? repoOwner, "treeseed-ai"),
|
|
738
|
+
name: slugify(input.contentRepository.name, `${repoName}-content`),
|
|
739
|
+
url: input.contentRepository.url,
|
|
740
|
+
visibility: input.contentRepository.visibility ?? input.repoVisibility ?? "private"
|
|
741
|
+
} : await createGitHubRepository({
|
|
742
|
+
owner: slugify(input.contentRepository.owner ?? repoOwner, "treeseed-ai"),
|
|
743
|
+
name: slugify(input.contentRepository.name, `${repoName}-content`),
|
|
744
|
+
description: input.summary ?? `Content source for ${input.projectName}`,
|
|
745
|
+
visibility: input.contentRepository.visibility ?? input.repoVisibility ?? "private",
|
|
746
|
+
homepageUrl: resolveManagedWebUrl(repoName),
|
|
747
|
+
topics: ["knowledge-coop", "treeseed", "knowledge-hub", "content"]
|
|
748
|
+
}, { env: githubEnv });
|
|
749
|
+
const contentInitResult = initializeGitHubRepositoryWorkingTree(contentRepositoryWorkingRoot, createdContentRepository, {
|
|
750
|
+
defaultBranch: input.contentRepository.defaultBranch ?? "main",
|
|
751
|
+
createStaging: true,
|
|
752
|
+
commitMessage: `Initialize ${input.projectName} content`
|
|
753
|
+
});
|
|
754
|
+
contentRepository = {
|
|
755
|
+
slug: createdContentRepository.slug,
|
|
756
|
+
owner: createdContentRepository.owner,
|
|
757
|
+
name: createdContentRepository.name,
|
|
758
|
+
url: createdContentRepository.url,
|
|
759
|
+
defaultBranch: contentInitResult.defaultBranch,
|
|
760
|
+
stagingBranch: contentInitResult.stagingBranch,
|
|
761
|
+
visibility: createdContentRepository.visibility
|
|
762
|
+
};
|
|
763
|
+
await appendPhase(phases, "content_repository", "completed", `${input.contentRepository.url ? "Connected" : "Created"} ${contentRepository.slug}.`, reportPhase);
|
|
764
|
+
stripSoftwareContentOverlay(workingRoot, input);
|
|
765
|
+
}
|
|
766
|
+
await appendPhase(phases, "workflow_bootstrap", "running", "Initializing git branches and GitHub workflows.", reportPhase);
|
|
670
767
|
const initResult = initializeGitHubRepositoryWorkingTree(workingRoot, repository, {
|
|
671
768
|
defaultBranch: "main",
|
|
672
769
|
createStaging: true,
|
|
@@ -685,8 +782,8 @@ async function executeKnowledgeCoopManagedLaunch(input) {
|
|
|
685
782
|
}));
|
|
686
783
|
}
|
|
687
784
|
const workflowSummary = { ...workflows, environmentSync: githubEnvironmentSync };
|
|
688
|
-
appendPhase(phases, "workflow_bootstrap", "completed", "Configured GitHub workflows, secrets, and variables.");
|
|
689
|
-
appendPhase(phases, "hosting_registration", "running", "Provisioning Cloudflare resources and deploy state.");
|
|
785
|
+
await appendPhase(phases, "workflow_bootstrap", "completed", "Configured GitHub workflows, secrets, and variables.", reportPhase);
|
|
786
|
+
await appendPhase(phases, "hosting_registration", "running", "Provisioning Cloudflare resources and deploy state.", reportPhase);
|
|
690
787
|
const staging = await reconcileTreeseedTarget({
|
|
691
788
|
tenantRoot: workingRoot,
|
|
692
789
|
target: createPersistentDeployTarget("staging"),
|
|
@@ -703,7 +800,7 @@ async function executeKnowledgeCoopManagedLaunch(input) {
|
|
|
703
800
|
target: createPersistentDeployTarget("prod"),
|
|
704
801
|
env: { ...process.env, ...prodEnvOverlay }
|
|
705
802
|
});
|
|
706
|
-
appendPhase(phases, "hosting_registration", "completed", "Provisioned Cloudflare resources.");
|
|
803
|
+
await appendPhase(phases, "hosting_registration", "completed", "Provisioned Cloudflare resources.", reportPhase);
|
|
707
804
|
const launchConfig = loadCliDeployConfig(workingRoot);
|
|
708
805
|
const managedRuntime = launchConfig.runtime?.mode === "treeseed_managed";
|
|
709
806
|
let services = [];
|
|
@@ -711,7 +808,7 @@ async function executeKnowledgeCoopManagedLaunch(input) {
|
|
|
711
808
|
let schedules = [];
|
|
712
809
|
let railwayVerification = [];
|
|
713
810
|
if (managedRuntime) {
|
|
714
|
-
appendPhase(phases, "runtime_connection", "running", "Deploying Railway services and registering runtime connectivity.");
|
|
811
|
+
await appendPhase(phases, "runtime_connection", "running", "Deploying Railway services and registering runtime connectivity.", reportPhase);
|
|
715
812
|
const railwayEnv = { ...process.env, ...prodEnvOverlay };
|
|
716
813
|
validateRailwayDeployPrerequisites(workingRoot, "prod", { env: railwayEnv });
|
|
717
814
|
services = configuredRailwayServices(workingRoot, "prod");
|
|
@@ -722,9 +819,9 @@ async function executeKnowledgeCoopManagedLaunch(input) {
|
|
|
722
819
|
schedules = await ensureRailwayScheduledJobs(workingRoot, "prod", { env: railwayEnv });
|
|
723
820
|
railwayVerification = await verifyRailwayScheduledJobs(workingRoot, "prod", { env: railwayEnv });
|
|
724
821
|
finalizeDeploymentState(workingRoot, { scope: "prod", serviceResults: deployments });
|
|
725
|
-
appendPhase(phases, "runtime_connection", "completed", "Deployed Railway services and recorded runtime readiness.");
|
|
822
|
+
await appendPhase(phases, "runtime_connection", "completed", "Deployed Railway services and recorded runtime readiness.", reportPhase);
|
|
726
823
|
} else {
|
|
727
|
-
appendPhase(phases, "runtime_connection", "completed", "Skipped managed runtime deployment for hub-only or BYO runtime launch.");
|
|
824
|
+
await appendPhase(phases, "runtime_connection", "completed", "Skipped managed runtime deployment for hub-only or BYO runtime launch.", reportPhase);
|
|
728
825
|
}
|
|
729
826
|
const defaultWorkstream = createDefaultWorkstream(input.projectId, input, seed);
|
|
730
827
|
const projectMetadata = loadProjectMetadata(
|
|
@@ -736,7 +833,8 @@ async function executeKnowledgeCoopManagedLaunch(input) {
|
|
|
736
833
|
managedDefaults.projectApiBaseUrl,
|
|
737
834
|
{ slug: repository.slug, url: repository.url }
|
|
738
835
|
);
|
|
739
|
-
const
|
|
836
|
+
const packageRoot = packageSourceRoot ?? workingRoot;
|
|
837
|
+
const templatePackage = buildKnowledgeCoopTemplatePackage(packageRoot, {
|
|
740
838
|
projectSlug: input.projectSlug,
|
|
741
839
|
title: `${input.projectName} template`,
|
|
742
840
|
summary: input.summary ?? null,
|
|
@@ -749,7 +847,7 @@ async function executeKnowledgeCoopManagedLaunch(input) {
|
|
|
749
847
|
}
|
|
750
848
|
}
|
|
751
849
|
});
|
|
752
|
-
const knowledgePackPackage = buildKnowledgeCoopKnowledgePackPackage(
|
|
850
|
+
const knowledgePackPackage = buildKnowledgeCoopKnowledgePackPackage(packageRoot, {
|
|
753
851
|
projectSlug: input.projectSlug,
|
|
754
852
|
title: `${input.projectName} knowledge pack`,
|
|
755
853
|
summary: input.summary ?? null,
|
|
@@ -769,10 +867,12 @@ async function executeKnowledgeCoopManagedLaunch(input) {
|
|
|
769
867
|
owner: repository.owner,
|
|
770
868
|
name: repository.name,
|
|
771
869
|
url: repository.url,
|
|
772
|
-
defaultBranch: initResult.defaultBranch,
|
|
773
|
-
stagingBranch: initResult.stagingBranch,
|
|
870
|
+
defaultBranch: input.existingRepository?.defaultBranch ?? initResult.defaultBranch,
|
|
871
|
+
stagingBranch: input.existingRepository?.stagingBranch ?? initResult.stagingBranch,
|
|
774
872
|
visibility: repository.visibility
|
|
775
873
|
},
|
|
874
|
+
contentRepository,
|
|
875
|
+
contentRepositoryWorkingRoot,
|
|
776
876
|
workflows: workflowSummary,
|
|
777
877
|
cloudflare: {
|
|
778
878
|
staging,
|
|
@@ -795,16 +895,19 @@ async function executeKnowledgeCoopManagedLaunch(input) {
|
|
|
795
895
|
};
|
|
796
896
|
} catch (error) {
|
|
797
897
|
const message = error instanceof Error ? error.message : String(error);
|
|
798
|
-
const phase = error instanceof
|
|
799
|
-
appendPhase(phases, phase.replace(/_failed$/u, ""), "failed", message);
|
|
800
|
-
throw new
|
|
898
|
+
const phase = error instanceof KnowledgeHubProviderLaunchError ? error.phase : phases.some((entry) => entry.phase === "runtime_connection" && entry.status === "running") ? "runtime_connection_failed" : phases.some((entry) => entry.phase === "hosting_registration" && entry.status === "running") ? "hosting_registration_failed" : phases.some((entry) => entry.phase === "workflow_bootstrap" && entry.status === "running") ? "workflow_bootstrap_failed" : phases.some((entry) => entry.phase === "content_bootstrap" && entry.status === "running") ? "content_bootstrap_failed" : "repo_provision_failed";
|
|
899
|
+
await appendPhase(phases, phase.replace(/_failed$/u, ""), "failed", message, reportPhase);
|
|
900
|
+
throw new KnowledgeHubProviderLaunchError(phase, message, phases);
|
|
801
901
|
} finally {
|
|
802
902
|
if (input.preserveWorkingTree === false) {
|
|
803
903
|
rmSync(workingRoot, { recursive: true, force: true });
|
|
804
904
|
}
|
|
905
|
+
if (packageSourceRoot && packageSourceRoot !== workingRoot && input.preserveWorkingTree === false) {
|
|
906
|
+
rmSync(packageSourceRoot, { recursive: true, force: true });
|
|
907
|
+
}
|
|
805
908
|
}
|
|
806
909
|
}
|
|
807
910
|
export {
|
|
808
|
-
|
|
809
|
-
|
|
911
|
+
executeKnowledgeHubProviderLaunch,
|
|
912
|
+
validateKnowledgeHubProviderLaunchPrerequisites
|
|
810
913
|
};
|
|
@@ -1230,7 +1230,11 @@ async function monitorProjectPlatform(options) {
|
|
|
1230
1230
|
r2: options.dryRun ? { ok: true, skipped: true, reason: "dry_run" } : probeR2(options.tenantRoot, siteConfig, state, target),
|
|
1231
1231
|
queue: options.dryRun ? Promise.resolve({ ok: true, skipped: true, reason: "dry_run" }) : probeQueue(siteConfig, state),
|
|
1232
1232
|
scaleProbe: probeScaleConfiguration(siteConfig, state),
|
|
1233
|
-
railwayResources: options.scope === "local" || !apiSelected && !agentsSelected ? Promise.resolve({ ok: true, skipped: true, reason: options.scope === "local" ? "local_scope" : "railway_not_selected" }) : verifyRailwayManagedResources(options.tenantRoot, options.scope, {
|
|
1233
|
+
railwayResources: options.scope === "local" || !apiSelected && !agentsSelected ? Promise.resolve({ ok: true, skipped: true, reason: options.scope === "local" ? "local_scope" : "railway_not_selected" }) : verifyRailwayManagedResources(options.tenantRoot, options.scope, {
|
|
1234
|
+
env,
|
|
1235
|
+
settleDeployments: true,
|
|
1236
|
+
onProgress: options.write
|
|
1237
|
+
}),
|
|
1234
1238
|
readiness: state.readiness
|
|
1235
1239
|
};
|
|
1236
1240
|
const resolvedChecks = {
|
|
@@ -13,7 +13,7 @@ export declare function runRailway(args: any, { cwd, capture, allowFailure, inpu
|
|
|
13
13
|
capture?: boolean | undefined;
|
|
14
14
|
allowFailure?: boolean | undefined;
|
|
15
15
|
}): import("child_process").SpawnSyncReturns<string>;
|
|
16
|
-
export declare function waitForRailwayManagedDeploymentsSettled(tenantRoot: any, scope: any, { services, env, timeoutMs, pollMs, }?: {
|
|
16
|
+
export declare function waitForRailwayManagedDeploymentsSettled(tenantRoot: any, scope: any, { services, env, timeoutMs, pollMs, onProgress, }?: {
|
|
17
17
|
services?: ({
|
|
18
18
|
key: string;
|
|
19
19
|
scope: string;
|
|
@@ -319,7 +319,7 @@ export declare function verifyRailwayScheduledJobs(tenantRoot: any, scope: any,
|
|
|
319
319
|
unsupported?: undefined;
|
|
320
320
|
message?: undefined;
|
|
321
321
|
}>;
|
|
322
|
-
export declare function verifyRailwayManagedResources(tenantRoot: any, scope: any, { fetchImpl, apiToken, apiUrl, env, settleDeployments, settleTimeoutMs, settlePollMs, }?: {
|
|
322
|
+
export declare function verifyRailwayManagedResources(tenantRoot: any, scope: any, { fetchImpl, apiToken, apiUrl, env, settleDeployments, settleTimeoutMs, settlePollMs, onProgress, }?: {
|
|
323
323
|
fetchImpl?: typeof fetch | undefined;
|
|
324
324
|
env?: NodeJS.ProcessEnv | undefined;
|
|
325
325
|
settleDeployments?: boolean | undefined;
|
|
@@ -112,6 +112,21 @@ function railwayStatusDeploymentSettled(status) {
|
|
|
112
112
|
const normalized = String(status ?? "").trim().toUpperCase();
|
|
113
113
|
return normalized === "SUCCESS" || normalized === "SLEEPING";
|
|
114
114
|
}
|
|
115
|
+
function formatRailwayDeploymentStatusSummary(scope, checks) {
|
|
116
|
+
const aliases = {
|
|
117
|
+
api: "api",
|
|
118
|
+
workdayManager: "manager",
|
|
119
|
+
workerRunner: "runner"
|
|
120
|
+
};
|
|
121
|
+
const parts = checks.map((check) => {
|
|
122
|
+
const name = aliases[check.service] ?? String(check.serviceName ?? check.service ?? "service");
|
|
123
|
+
const status = String(check.status ?? "unknown").toUpperCase();
|
|
124
|
+
const instanceStatuses = Array.isArray(check.observed?.instanceStatuses) && check.observed.instanceStatuses.length > 0 ? `/${check.observed.instanceStatuses.join("+")}` : "";
|
|
125
|
+
const stopped = check.observed?.deploymentStopped === true ? "/stopped" : "";
|
|
126
|
+
return `${name}=${status}${instanceStatuses}${stopped}`;
|
|
127
|
+
});
|
|
128
|
+
return `[railway][monitor][${scope}] ${parts.join(" ")}`;
|
|
129
|
+
}
|
|
115
130
|
function collectRailwayDeploymentStatusChecks(statusPayload, scope, services) {
|
|
116
131
|
const expectedEnvironment = resolveRailwayEnvironmentForScope(scope);
|
|
117
132
|
const environments = railwayStatusEnvironmentNodes(statusPayload);
|
|
@@ -394,7 +409,8 @@ async function waitForRailwayManagedDeploymentsSettled(tenantRoot, scope, {
|
|
|
394
409
|
services = configuredRailwayServices(tenantRoot, scope),
|
|
395
410
|
env = process.env,
|
|
396
411
|
timeoutMs = 6e5,
|
|
397
|
-
pollMs = 15e3
|
|
412
|
+
pollMs = 15e3,
|
|
413
|
+
onProgress
|
|
398
414
|
} = {}) {
|
|
399
415
|
const deadline = Date.now() + timeoutMs;
|
|
400
416
|
const projectId = services.find((service) => typeof service.projectId === "string" && service.projectId.trim())?.projectId ?? null;
|
|
@@ -414,6 +430,7 @@ async function waitForRailwayManagedDeploymentsSettled(tenantRoot, scope, {
|
|
|
414
430
|
}
|
|
415
431
|
let checks = [];
|
|
416
432
|
let lastError = null;
|
|
433
|
+
let lastSummary = "";
|
|
417
434
|
for (; ; ) {
|
|
418
435
|
lastError = null;
|
|
419
436
|
try {
|
|
@@ -434,6 +451,11 @@ async function waitForRailwayManagedDeploymentsSettled(tenantRoot, scope, {
|
|
|
434
451
|
message: error instanceof Error ? error.message : String(error)
|
|
435
452
|
}));
|
|
436
453
|
}
|
|
454
|
+
const summary = formatRailwayDeploymentStatusSummary(scope, checks);
|
|
455
|
+
if (summary !== lastSummary || !checks.every((entry) => entry.ok === true)) {
|
|
456
|
+
onProgress?.(summary, "stdout");
|
|
457
|
+
lastSummary = summary;
|
|
458
|
+
}
|
|
437
459
|
if (checks.every((entry) => entry.ok === true)) {
|
|
438
460
|
return { ok: true, checks };
|
|
439
461
|
}
|
|
@@ -1017,7 +1039,8 @@ async function verifyRailwayManagedResources(tenantRoot, scope, {
|
|
|
1017
1039
|
env = process.env,
|
|
1018
1040
|
settleDeployments = false,
|
|
1019
1041
|
settleTimeoutMs = 6e5,
|
|
1020
|
-
settlePollMs = 15e3
|
|
1042
|
+
settlePollMs = 15e3,
|
|
1043
|
+
onProgress
|
|
1021
1044
|
} = {}) {
|
|
1022
1045
|
const effectiveApiToken = apiToken || resolveRailwayAuthToken(env);
|
|
1023
1046
|
const effectiveApiUrl = apiUrl || resolveRailwayApiUrl(env);
|
|
@@ -1129,7 +1152,8 @@ async function verifyRailwayManagedResources(tenantRoot, scope, {
|
|
|
1129
1152
|
services: deploymentStatusServices.length > 0 ? deploymentStatusServices : services,
|
|
1130
1153
|
env: effectiveEnv,
|
|
1131
1154
|
timeoutMs: settleTimeoutMs,
|
|
1132
|
-
pollMs: settlePollMs
|
|
1155
|
+
pollMs: settlePollMs,
|
|
1156
|
+
onProgress
|
|
1133
1157
|
});
|
|
1134
1158
|
for (const check of settled.checks ?? []) {
|
|
1135
1159
|
checks.push(check);
|
|
@@ -33,6 +33,21 @@ const TRESEED_OPERATION_SPECS = [
|
|
|
33
33
|
operation({ id: "template.sync", name: "sync", aliases: [], group: "Validation", summary: "Validate or reconcile the managed template surface for the current site.", description: "Use remote template metadata plus the local scaffold artifact to check or apply updates to the managed scaffold surface.", provider: "default", related: ["template", "init", "status"] }),
|
|
34
34
|
operation({ id: "project.init", name: "init", aliases: [], group: "Workflow", summary: "Scaffold a new Treeseed tenant project.", description: "Create a new Treeseed tenant directory from a remote-catalog template backed by the packaged scaffold artifact.", provider: "default", related: ["config", "switch", "dev"] }),
|
|
35
35
|
operation({ id: "project.config", name: "config", aliases: [], group: "Workflow", summary: "Configure and test the runtime foundation.", description: "Apply safe repairs, collect environment values, write local machine config, initialize environments, sync providers, and run doctor-style checks.", provider: "default", related: ["status", "switch", "dev"] }),
|
|
36
|
+
operation({ id: "hub.planLaunch", name: "hub.plan_launch", aliases: [], group: "Workflow", summary: "Plan an online Knowledge Hub launch.", description: "Normalize a Knowledge Hub launch intent, resolve repository topology, and return the durable launch plan shared by CLI and Market.", provider: "default", related: ["hub.validate_launch", "hub.execute_launch"] }),
|
|
37
|
+
operation({ id: "hub.validateLaunch", name: "hub.validate_launch", aliases: [], group: "Validation", summary: "Validate an online Knowledge Hub launch intent.", description: "Validate the shared Knowledge Hub launch intent and repository plan before execution.", provider: "default", related: ["hub.plan_launch", "hub.execute_launch"] }),
|
|
38
|
+
operation({ id: "hub.executeLaunch", name: "hub.execute_launch", aliases: [], group: "Workflow", summary: "Execute an online Knowledge Hub launch.", description: "Execute a Knowledge Hub launch through the shared SDK launch contract.", provider: "default", related: ["hub.plan_launch", "hub.resume_launch"] }),
|
|
39
|
+
operation({ id: "hub.resumeLaunch", name: "hub.resume_launch", aliases: [], group: "Workflow", summary: "Resume an online Knowledge Hub launch.", description: "Resume a previously planned Knowledge Hub launch from durable launch state.", provider: "default", related: ["hub.execute_launch"] }),
|
|
40
|
+
operation({ id: "hub.planUpdate", name: "hub.plan_update", aliases: [], group: "Workflow", summary: "Plan a Knowledge Hub update.", description: "Create a preview plan for template, knowledge pack, runtime, capability, or repository-topology updates.", provider: "default", related: ["hub.validate_update", "hub.execute_update"] }),
|
|
41
|
+
operation({ id: "hub.validateUpdate", name: "hub.validate_update", aliases: [], group: "Validation", summary: "Validate a Knowledge Hub update plan.", description: "Validate a planned update before it becomes binding work.", provider: "default", related: ["hub.plan_update"] }),
|
|
42
|
+
operation({ id: "hub.executeUpdate", name: "hub.execute_update", aliases: [], group: "Workflow", summary: "Execute a Knowledge Hub update.", description: "Apply a capability-gated Knowledge Hub update after required review or Decision approval.", provider: "default", related: ["hub.plan_update", "hub.resume_update"] }),
|
|
43
|
+
operation({ id: "hub.resumeUpdate", name: "hub.resume_update", aliases: [], group: "Workflow", summary: "Resume a Knowledge Hub update.", description: "Resume a previously planned Knowledge Hub update from durable state.", provider: "default", related: ["hub.execute_update"] }),
|
|
44
|
+
operation({ id: "repositoryHost.validate", name: "repository_host.validate", aliases: [], group: "Validation", summary: "Validate Repository Host configuration.", description: "Validate a GitHub Repository Host for Knowledge Hub repository provisioning.", provider: "default", related: ["repository_host.create_repositories"] }),
|
|
45
|
+
operation({ id: "repositoryHost.createRepositories", name: "repository_host.create_repositories", aliases: [], group: "Workflow", summary: "Create or connect Knowledge Hub repositories.", description: "Create or connect the software and content repositories for a Knowledge Hub repository plan.", provider: "default", related: ["hub.plan_launch"] }),
|
|
46
|
+
operation({ id: "content.verifyPackage", name: "content.verify_package", aliases: [], group: "Validation", summary: "Verify a content package before publishing.", description: "Verify Knowledge Hub content package metadata before publishing content artifacts.", provider: "default", related: ["content.publish"] }),
|
|
47
|
+
operation({ id: "content.publish", name: "content.publish", aliases: [], group: "Workflow", summary: "Publish Knowledge Hub content artifacts.", description: "Publish verified Knowledge Hub content artifacts to the configured content target.", provider: "default", related: ["content.verify_package"] }),
|
|
48
|
+
operation({ id: "workspace.planAttachParent", name: "workspace.plan_attach_parent", aliases: [], group: "Workflow", summary: "Plan parent workspace attachment.", description: "Plan how a Knowledge Hub software/content repository pair attaches to a parent repository workspace.", provider: "default", related: ["workspace.attach_parent"] }),
|
|
49
|
+
operation({ id: "workspace.attachParent", name: "workspace.attach_parent", aliases: [], group: "Workflow", summary: "Attach a parent workspace.", description: "Attach a parent repository workspace after technical steward approval.", provider: "default", related: ["workspace.plan_attach_parent", "workspace.update_submodule_pointers"] }),
|
|
50
|
+
operation({ id: "workspace.updateSubmodulePointers", name: "workspace.update_submodule_pointers", aliases: [], group: "Workflow", summary: "Update workspace submodule pointers.", description: "Update parent workspace submodule pointers for software and content repositories.", provider: "default", related: ["workspace.attach_parent"] }),
|
|
36
51
|
operation({ id: "project.export", name: "export", aliases: [], group: "Utilities", summary: "Export a Markdown snapshot of the current codebase.", description: "Generate a Markdown codebase snapshot for the selected directory using the SDK-owned repomix integration and store it under .treeseed/exports.", provider: "default", related: ["status", "config"] }),
|
|
37
52
|
operation({ id: "deploy.release", name: "release", aliases: [], group: "Workflow", summary: "Release changed packages and market from staging to production.", description: "Select changed packages plus dependents, validate publish workflows, release packages first, then promote market from staging to main with aligned package pointers.", provider: "default", related: ["stage", "status", "rollback"] }),
|
|
38
53
|
operation({ id: "deploy.destroy", name: "destroy", aliases: [], group: "Workflow", summary: "Destroy a persistent environment and its local state.", description: "Delete the selected persistent environment resources and remove the local deploy state after confirmation.", provider: "default", related: ["config", "status"] }),
|
|
@@ -44,6 +44,7 @@ export type TreeseedOperationContext = {
|
|
|
44
44
|
cwd: string;
|
|
45
45
|
env: NodeJS.ProcessEnv;
|
|
46
46
|
write?: TreeseedOperationWriter;
|
|
47
|
+
onProgress?: (event: Record<string, unknown>) => void | Promise<void>;
|
|
47
48
|
spawn?: TreeseedOperationSpawn;
|
|
48
49
|
outputFormat?: 'human' | 'json';
|
|
49
50
|
prompt?: TreeseedOperationPrompt;
|
package/dist/operations.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export { TRESEED_OPERATION_SPECS, findTreeseedOperation, listTreeseedOperationNames, } from './operations-registry.ts';
|
|
2
2
|
export { collectTreeseedConfigSeedValues } from './operations/services/config-runtime.ts';
|
|
3
|
+
export { createKnowledgeHubRepositories, defaultHubContentResolutionPolicy, executeKnowledgeHubLaunch, normalizeKnowledgeHubLaunchIntent, planKnowledgeHubLaunch, planKnowledgeHubRepositories, validateRepositoryHost, } from './operations/services/hub-launch.ts';
|
|
3
4
|
export { TreeseedOperationsSdk } from './operations/runtime.ts';
|
|
5
|
+
export type { HubContentResolutionPolicy, KnowledgeHubLaunchIntent, KnowledgeHubLaunchPhase, KnowledgeHubLaunchPlan, KnowledgeHubLaunchResult, KnowledgeHubRepositoryPlan, RepositoryHost, } from './operations/services/hub-launch.ts';
|
|
4
6
|
export type { TreeseedOperationContext, TreeseedOperationImplementation, TreeseedOperationId, TreeseedOperationMetadata, TreeseedOperationProvider, TreeseedOperationProviderId, TreeseedOperationRequest, TreeseedOperationResult, TreeseedOperationGroup, } from './operations-types.ts';
|
|
5
7
|
export { TreeseedOperationError } from './operations-types.ts';
|
|
6
8
|
export { TreeseedWorkflowSdk } from './workflow.ts';
|
package/dist/operations.js
CHANGED
|
@@ -4,6 +4,15 @@ import {
|
|
|
4
4
|
listTreeseedOperationNames
|
|
5
5
|
} from "./operations-registry.js";
|
|
6
6
|
import { collectTreeseedConfigSeedValues } from "./operations/services/config-runtime.js";
|
|
7
|
+
import {
|
|
8
|
+
createKnowledgeHubRepositories,
|
|
9
|
+
defaultHubContentResolutionPolicy,
|
|
10
|
+
executeKnowledgeHubLaunch,
|
|
11
|
+
normalizeKnowledgeHubLaunchIntent,
|
|
12
|
+
planKnowledgeHubLaunch,
|
|
13
|
+
planKnowledgeHubRepositories,
|
|
14
|
+
validateRepositoryHost
|
|
15
|
+
} from "./operations/services/hub-launch.js";
|
|
7
16
|
import { TreeseedOperationsSdk } from "./operations/runtime.js";
|
|
8
17
|
import { TreeseedOperationError } from "./operations-types.js";
|
|
9
18
|
import { TreeseedWorkflowSdk } from "./workflow.js";
|
|
@@ -13,6 +22,13 @@ export {
|
|
|
13
22
|
TreeseedOperationsSdk,
|
|
14
23
|
TreeseedWorkflowSdk,
|
|
15
24
|
collectTreeseedConfigSeedValues,
|
|
25
|
+
createKnowledgeHubRepositories,
|
|
26
|
+
defaultHubContentResolutionPolicy,
|
|
27
|
+
executeKnowledgeHubLaunch,
|
|
16
28
|
findTreeseedOperation,
|
|
17
|
-
listTreeseedOperationNames
|
|
29
|
+
listTreeseedOperationNames,
|
|
30
|
+
normalizeKnowledgeHubLaunchIntent,
|
|
31
|
+
planKnowledgeHubLaunch,
|
|
32
|
+
planKnowledgeHubRepositories,
|
|
33
|
+
validateRepositoryHost
|
|
18
34
|
};
|
package/dist/remote.d.ts
CHANGED
|
@@ -230,4 +230,15 @@ export declare class RemoteTreeseedRunnerClient {
|
|
|
230
230
|
ok: true;
|
|
231
231
|
payload: RemoteJob;
|
|
232
232
|
}>;
|
|
233
|
+
consumeCredentialSession(jobId: string, sessionId: string): Promise<{
|
|
234
|
+
ok: true;
|
|
235
|
+
payload: {
|
|
236
|
+
id: string;
|
|
237
|
+
hostKind: string;
|
|
238
|
+
hostId: string;
|
|
239
|
+
purpose: string;
|
|
240
|
+
provider?: string | null;
|
|
241
|
+
config: Record<string, string>;
|
|
242
|
+
};
|
|
243
|
+
}>;
|
|
233
244
|
}
|
package/dist/remote.js
CHANGED
|
@@ -262,6 +262,12 @@ class RemoteTreeseedRunnerClient {
|
|
|
262
262
|
requireAuth: true
|
|
263
263
|
});
|
|
264
264
|
}
|
|
265
|
+
consumeCredentialSession(jobId, sessionId) {
|
|
266
|
+
return this.client.requestJson(`/v1/jobs/${encodeURIComponent(jobId)}/provider-credential-sessions/${encodeURIComponent(sessionId)}/consume`, {
|
|
267
|
+
method: "POST",
|
|
268
|
+
requireAuth: true
|
|
269
|
+
});
|
|
270
|
+
}
|
|
265
271
|
}
|
|
266
272
|
export {
|
|
267
273
|
CloudflareQueuePullClient,
|