@treeseed/sdk 0.6.51 → 0.8.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/build-warning-policy.js +9 -2
- 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-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/package.json +1 -1
|
@@ -200,7 +200,7 @@ async function ensureGitHubBootstrapRepository(tenantRoot, {
|
|
|
200
200
|
mode: "real"
|
|
201
201
|
};
|
|
202
202
|
}
|
|
203
|
-
async function createGitHubRepository(input) {
|
|
203
|
+
async function createGitHubRepository(input, { env = process.env } = {}) {
|
|
204
204
|
const visibility = input.visibility ?? "private";
|
|
205
205
|
const remotes = resolveGitHubRemoteUrls(input.owner, input.name);
|
|
206
206
|
return await ensureGitHubRepository({
|
|
@@ -211,7 +211,7 @@ async function createGitHubRepository(input) {
|
|
|
211
211
|
visibility,
|
|
212
212
|
topics: Array.isArray(input.topics) ? input.topics.map((topic) => slugifySegment(topic, "treeseed")) : []
|
|
213
213
|
}, {
|
|
214
|
-
client: createGitHubApiClient()
|
|
214
|
+
client: createGitHubApiClient({ env })
|
|
215
215
|
});
|
|
216
216
|
}
|
|
217
217
|
function initializeGitHubRepositoryWorkingTree(cwd, repository, {
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { type KnowledgeHubProviderLaunchInput, type KnowledgeHubProviderLaunchResult } from './hub-provider-launch.ts';
|
|
2
|
+
export type KnowledgeHubSourceKind = 'blank_hub' | 'template' | 'knowledge_pack' | 'market_listing';
|
|
3
|
+
export type KnowledgeHubRepositoryTopology = 'split_software_content' | 'combined_compatibility';
|
|
4
|
+
export type KnowledgeHubRepositoryRole = 'software' | 'content' | 'parent_workspace';
|
|
5
|
+
export type KnowledgeHubHostMode = 'treeseed_managed' | 'team_owned' | 'self_hosted' | 'hybrid';
|
|
6
|
+
export type KnowledgeHubLaunchPhaseStatus = 'queued' | 'running' | 'completed' | 'failed' | 'blocked';
|
|
7
|
+
export interface RepositoryHost {
|
|
8
|
+
id?: string;
|
|
9
|
+
teamId?: string | null;
|
|
10
|
+
provider: 'github';
|
|
11
|
+
ownership: 'treeseed_managed' | 'team_owned';
|
|
12
|
+
name: string;
|
|
13
|
+
accountLabel?: string | null;
|
|
14
|
+
organizationOrOwner: string;
|
|
15
|
+
defaultVisibility?: 'private' | 'internal' | 'public';
|
|
16
|
+
softwareRepositoryNameTemplate?: string;
|
|
17
|
+
contentRepositoryNameTemplate?: string;
|
|
18
|
+
branchPolicy?: Record<string, unknown>;
|
|
19
|
+
workflowPolicy?: Record<string, unknown>;
|
|
20
|
+
allowedProjectKinds?: string[];
|
|
21
|
+
status?: 'active' | 'inactive' | 'needs_attention';
|
|
22
|
+
}
|
|
23
|
+
export interface RepositorySelection {
|
|
24
|
+
owner?: string;
|
|
25
|
+
name?: string;
|
|
26
|
+
url?: string | null;
|
|
27
|
+
defaultBranch?: string | null;
|
|
28
|
+
}
|
|
29
|
+
export interface HubContentResolutionPolicy {
|
|
30
|
+
productionSource: 'r2_published_artifacts';
|
|
31
|
+
overlaySource?: 'src_content_when_present';
|
|
32
|
+
localSource?: 'local_content_checkout';
|
|
33
|
+
fallback?: 'empty_with_diagnostics' | 'r2_published_artifacts';
|
|
34
|
+
}
|
|
35
|
+
export interface KnowledgeHubLaunchIntent {
|
|
36
|
+
team: {
|
|
37
|
+
id: string;
|
|
38
|
+
slug?: string | null;
|
|
39
|
+
};
|
|
40
|
+
hub: {
|
|
41
|
+
id?: string;
|
|
42
|
+
name: string;
|
|
43
|
+
slug: string;
|
|
44
|
+
purpose?: string | null;
|
|
45
|
+
visibility?: 'private' | 'team' | 'public';
|
|
46
|
+
};
|
|
47
|
+
source?: {
|
|
48
|
+
kind?: KnowledgeHubSourceKind | 'blank';
|
|
49
|
+
ref?: string | null;
|
|
50
|
+
version?: string | null;
|
|
51
|
+
};
|
|
52
|
+
repository?: {
|
|
53
|
+
hostId?: string | null;
|
|
54
|
+
provider?: 'github';
|
|
55
|
+
owner?: string | null;
|
|
56
|
+
topology?: KnowledgeHubRepositoryTopology;
|
|
57
|
+
softwareRepository?: RepositorySelection | null;
|
|
58
|
+
contentRepository?: RepositorySelection | null;
|
|
59
|
+
visibility?: 'private' | 'internal' | 'public';
|
|
60
|
+
};
|
|
61
|
+
hosting?: {
|
|
62
|
+
mode?: KnowledgeHubHostMode | 'managed';
|
|
63
|
+
webHost?: Record<string, unknown> | null;
|
|
64
|
+
processingHost?: Record<string, unknown> | null;
|
|
65
|
+
};
|
|
66
|
+
contentResolution?: HubContentResolutionPolicy;
|
|
67
|
+
direction?: {
|
|
68
|
+
objective?: string | null;
|
|
69
|
+
question?: string | null;
|
|
70
|
+
proposal?: string | null;
|
|
71
|
+
decisionPolicyPreset?: 'fast_yes_no' | 'lead_approval' | 'team_poll' | 'role_gated';
|
|
72
|
+
};
|
|
73
|
+
capabilities?: Array<Record<string, unknown>>;
|
|
74
|
+
market?: {
|
|
75
|
+
createDraftListing?: boolean;
|
|
76
|
+
publisherTeamId?: string;
|
|
77
|
+
provenancePolicy?: 'private' | 'selected' | 'public';
|
|
78
|
+
};
|
|
79
|
+
execution?: {
|
|
80
|
+
providerLaunchInput?: Partial<KnowledgeHubProviderLaunchInput>;
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
export interface KnowledgeHubRepositoryPlan {
|
|
84
|
+
topology: KnowledgeHubRepositoryTopology;
|
|
85
|
+
provider: 'github';
|
|
86
|
+
hostId?: string | null;
|
|
87
|
+
owner: string;
|
|
88
|
+
visibility: 'private' | 'internal' | 'public';
|
|
89
|
+
repositories: Array<{
|
|
90
|
+
role: KnowledgeHubRepositoryRole;
|
|
91
|
+
owner: string;
|
|
92
|
+
name: string;
|
|
93
|
+
url?: string | null;
|
|
94
|
+
defaultBranch?: string | null;
|
|
95
|
+
create: boolean;
|
|
96
|
+
}>;
|
|
97
|
+
}
|
|
98
|
+
export interface KnowledgeHubLaunchPlan {
|
|
99
|
+
intent: KnowledgeHubLaunchIntent;
|
|
100
|
+
repository: KnowledgeHubRepositoryPlan;
|
|
101
|
+
contentResolution: HubContentResolutionPolicy;
|
|
102
|
+
phases: KnowledgeHubLaunchPhase[];
|
|
103
|
+
}
|
|
104
|
+
export interface KnowledgeHubLaunchPhase {
|
|
105
|
+
phase: string;
|
|
106
|
+
status: KnowledgeHubLaunchPhaseStatus;
|
|
107
|
+
title: string;
|
|
108
|
+
summary?: string | null;
|
|
109
|
+
startedAt?: string | null;
|
|
110
|
+
finishedAt?: string | null;
|
|
111
|
+
data?: Record<string, unknown>;
|
|
112
|
+
error?: {
|
|
113
|
+
code?: string | null;
|
|
114
|
+
message: string;
|
|
115
|
+
} | null;
|
|
116
|
+
}
|
|
117
|
+
export interface KnowledgeHubLaunchResult {
|
|
118
|
+
intent: KnowledgeHubLaunchIntent;
|
|
119
|
+
plan: KnowledgeHubLaunchPlan;
|
|
120
|
+
repositories: KnowledgeHubRepositoryPlan['repositories'];
|
|
121
|
+
workingRoot: KnowledgeHubProviderLaunchResult['workingRoot'];
|
|
122
|
+
repository: KnowledgeHubProviderLaunchResult['repository'];
|
|
123
|
+
contentRepository?: KnowledgeHubProviderLaunchResult['contentRepository'];
|
|
124
|
+
contentRepositoryWorkingRoot?: KnowledgeHubProviderLaunchResult['contentRepositoryWorkingRoot'];
|
|
125
|
+
workflows: KnowledgeHubProviderLaunchResult['workflows'];
|
|
126
|
+
cloudflare: KnowledgeHubProviderLaunchResult['cloudflare'];
|
|
127
|
+
railway: KnowledgeHubProviderLaunchResult['railway'];
|
|
128
|
+
projectApiBaseUrl?: string | null;
|
|
129
|
+
projectSiteUrl?: string | null;
|
|
130
|
+
projectMetadata: KnowledgeHubProviderLaunchResult['projectMetadata'];
|
|
131
|
+
defaultWorkstream: KnowledgeHubProviderLaunchResult['defaultWorkstream'];
|
|
132
|
+
phases: KnowledgeHubLaunchPhase[];
|
|
133
|
+
templatePackage: KnowledgeHubProviderLaunchResult['templatePackage'];
|
|
134
|
+
knowledgePackPackage: KnowledgeHubProviderLaunchResult['knowledgePackPackage'];
|
|
135
|
+
metadata: Record<string, unknown>;
|
|
136
|
+
}
|
|
137
|
+
export interface KnowledgeHubLaunchExecutionOptions {
|
|
138
|
+
onPhase?: (phase: KnowledgeHubLaunchPhase) => void | Promise<void>;
|
|
139
|
+
}
|
|
140
|
+
export declare function normalizeKnowledgeHubSourceKind(kind: unknown): KnowledgeHubSourceKind;
|
|
141
|
+
export declare function normalizeKnowledgeHubLaunchIntent(input: KnowledgeHubLaunchIntent): KnowledgeHubLaunchIntent;
|
|
142
|
+
export declare function defaultHubContentResolutionPolicy(): HubContentResolutionPolicy;
|
|
143
|
+
export declare function planKnowledgeHubRepositories(intent: KnowledgeHubLaunchIntent, host?: RepositoryHost | null): KnowledgeHubRepositoryPlan;
|
|
144
|
+
export declare function planKnowledgeHubLaunch(input: KnowledgeHubLaunchIntent, host?: RepositoryHost | null): KnowledgeHubLaunchPlan;
|
|
145
|
+
export declare function validateRepositoryHost(host: RepositoryHost): {
|
|
146
|
+
ok: boolean;
|
|
147
|
+
issues: string[];
|
|
148
|
+
host: {
|
|
149
|
+
defaultVisibility: "private" | "public" | "internal";
|
|
150
|
+
softwareRepositoryNameTemplate: string;
|
|
151
|
+
contentRepositoryNameTemplate: string;
|
|
152
|
+
branchPolicy: Record<string, unknown>;
|
|
153
|
+
workflowPolicy: Record<string, unknown>;
|
|
154
|
+
allowedProjectKinds: string[];
|
|
155
|
+
status: "active" | "inactive" | "needs_attention";
|
|
156
|
+
id?: string;
|
|
157
|
+
teamId?: string | null;
|
|
158
|
+
provider: "github";
|
|
159
|
+
ownership: "treeseed_managed" | "team_owned";
|
|
160
|
+
name: string;
|
|
161
|
+
accountLabel?: string | null;
|
|
162
|
+
organizationOrOwner: string;
|
|
163
|
+
};
|
|
164
|
+
};
|
|
165
|
+
export declare function createKnowledgeHubRepositories(input: {
|
|
166
|
+
plan: KnowledgeHubRepositoryPlan;
|
|
167
|
+
dryRun?: boolean;
|
|
168
|
+
description?: string | null;
|
|
169
|
+
homepageUrl?: string | null;
|
|
170
|
+
}): Promise<{
|
|
171
|
+
repositories: {
|
|
172
|
+
status: string;
|
|
173
|
+
role: KnowledgeHubRepositoryRole;
|
|
174
|
+
owner: string;
|
|
175
|
+
name: string;
|
|
176
|
+
url?: string | null;
|
|
177
|
+
defaultBranch?: string | null;
|
|
178
|
+
create: boolean;
|
|
179
|
+
}[];
|
|
180
|
+
}>;
|
|
181
|
+
export declare function phaseFromProviderLaunch(entry: KnowledgeHubProviderLaunchResult['phases'][number]): KnowledgeHubLaunchPhase;
|
|
182
|
+
export declare function executeKnowledgeHubLaunch(input: KnowledgeHubLaunchIntent, options?: KnowledgeHubLaunchExecutionOptions): Promise<KnowledgeHubLaunchResult>;
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import { createGitHubRepository } from "./github-automation.js";
|
|
2
|
+
import {
|
|
3
|
+
executeKnowledgeHubProviderLaunch
|
|
4
|
+
} from "./hub-provider-launch.js";
|
|
5
|
+
function slugify(value, fallback = "hub") {
|
|
6
|
+
const slug = String(value ?? "").trim().toLowerCase().replace(/[^a-z0-9]+/gu, "-").replace(/^-+|-+$/gu, "");
|
|
7
|
+
return slug || fallback;
|
|
8
|
+
}
|
|
9
|
+
function renderRepositoryName(template, hubSlug, fallbackSuffix) {
|
|
10
|
+
const base = template && template.trim() ? template.trim() : `{hub}-${fallbackSuffix}`;
|
|
11
|
+
return slugify(base.replace(/\{hub\}/gu, hubSlug), `${hubSlug}-${fallbackSuffix}`);
|
|
12
|
+
}
|
|
13
|
+
function normalizeKnowledgeHubSourceKind(kind) {
|
|
14
|
+
if (kind === "blank" || kind === "blank_hub" || kind === void 0 || kind === null) return "blank_hub";
|
|
15
|
+
if (kind === "template" || kind === "knowledge_pack" || kind === "market_listing") return kind;
|
|
16
|
+
throw new Error(`Unsupported Knowledge Hub source kind "${String(kind)}".`);
|
|
17
|
+
}
|
|
18
|
+
function normalizeKnowledgeHubLaunchIntent(input) {
|
|
19
|
+
if (!input?.team?.id) throw new Error("Knowledge Hub launch intent requires team.id.");
|
|
20
|
+
if (!input?.hub?.name) throw new Error("Knowledge Hub launch intent requires hub.name.");
|
|
21
|
+
const slug = slugify(input.hub.slug || input.hub.name, "hub");
|
|
22
|
+
return {
|
|
23
|
+
...input,
|
|
24
|
+
hub: {
|
|
25
|
+
...input.hub,
|
|
26
|
+
slug,
|
|
27
|
+
visibility: input.hub.visibility ?? "team"
|
|
28
|
+
},
|
|
29
|
+
source: {
|
|
30
|
+
...input.source,
|
|
31
|
+
kind: normalizeKnowledgeHubSourceKind(input.source?.kind),
|
|
32
|
+
ref: input.source?.ref ?? null,
|
|
33
|
+
version: input.source?.version ?? null
|
|
34
|
+
},
|
|
35
|
+
repository: {
|
|
36
|
+
provider: "github",
|
|
37
|
+
topology: input.repository?.topology ?? "split_software_content",
|
|
38
|
+
visibility: input.repository?.visibility ?? "private",
|
|
39
|
+
hostId: input.repository?.hostId ?? null,
|
|
40
|
+
owner: input.repository?.owner ?? null,
|
|
41
|
+
softwareRepository: input.repository?.softwareRepository ?? null,
|
|
42
|
+
contentRepository: input.repository?.contentRepository ?? null
|
|
43
|
+
},
|
|
44
|
+
hosting: {
|
|
45
|
+
mode: input.hosting?.mode === "managed" ? "treeseed_managed" : input.hosting?.mode ?? "treeseed_managed",
|
|
46
|
+
webHost: input.hosting?.webHost ?? null,
|
|
47
|
+
processingHost: input.hosting?.processingHost ?? null
|
|
48
|
+
},
|
|
49
|
+
contentResolution: input.contentResolution ?? defaultHubContentResolutionPolicy(),
|
|
50
|
+
direction: input.direction ?? {},
|
|
51
|
+
capabilities: input.capabilities ?? [],
|
|
52
|
+
market: input.market ?? {}
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function defaultHubContentResolutionPolicy() {
|
|
56
|
+
return {
|
|
57
|
+
productionSource: "r2_published_artifacts",
|
|
58
|
+
overlaySource: "src_content_when_present",
|
|
59
|
+
localSource: "local_content_checkout",
|
|
60
|
+
fallback: "empty_with_diagnostics"
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function planKnowledgeHubRepositories(intent, host) {
|
|
64
|
+
const normalized = normalizeKnowledgeHubLaunchIntent(intent);
|
|
65
|
+
const hubSlug = normalized.hub.slug;
|
|
66
|
+
const owner = normalized.repository?.owner ?? host?.organizationOrOwner ?? process.env.TREESEED_HOSTED_HUBS_GITHUB_OWNER ?? process.env.TREESEED_REPOSITORY_HOST_GITHUB_OWNER ?? process.env.GITHUB_REPOSITORY_OWNER ?? "treeseed-sites";
|
|
67
|
+
const topology = normalized.repository?.topology ?? "split_software_content";
|
|
68
|
+
const visibility = normalized.repository?.visibility ?? host?.defaultVisibility ?? "private";
|
|
69
|
+
if (topology === "combined_compatibility") {
|
|
70
|
+
const name = normalized.repository?.softwareRepository?.name ?? hubSlug;
|
|
71
|
+
return {
|
|
72
|
+
topology,
|
|
73
|
+
provider: "github",
|
|
74
|
+
hostId: normalized.repository?.hostId ?? host?.id ?? null,
|
|
75
|
+
owner,
|
|
76
|
+
visibility,
|
|
77
|
+
repositories: [{
|
|
78
|
+
role: "software",
|
|
79
|
+
owner,
|
|
80
|
+
name,
|
|
81
|
+
url: normalized.repository?.softwareRepository?.url ?? null,
|
|
82
|
+
defaultBranch: normalized.repository?.softwareRepository?.defaultBranch ?? "main",
|
|
83
|
+
create: !normalized.repository?.softwareRepository?.url
|
|
84
|
+
}]
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
const softwareName = normalized.repository?.softwareRepository?.name ?? renderRepositoryName(host?.softwareRepositoryNameTemplate, hubSlug, "site");
|
|
88
|
+
const contentName = normalized.repository?.contentRepository?.name ?? renderRepositoryName(host?.contentRepositoryNameTemplate, hubSlug, "content");
|
|
89
|
+
return {
|
|
90
|
+
topology,
|
|
91
|
+
provider: "github",
|
|
92
|
+
hostId: normalized.repository?.hostId ?? host?.id ?? null,
|
|
93
|
+
owner,
|
|
94
|
+
visibility,
|
|
95
|
+
repositories: [
|
|
96
|
+
{
|
|
97
|
+
role: "software",
|
|
98
|
+
owner,
|
|
99
|
+
name: softwareName,
|
|
100
|
+
url: normalized.repository?.softwareRepository?.url ?? null,
|
|
101
|
+
defaultBranch: normalized.repository?.softwareRepository?.defaultBranch ?? "main",
|
|
102
|
+
create: !normalized.repository?.softwareRepository?.url
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
role: "content",
|
|
106
|
+
owner,
|
|
107
|
+
name: contentName,
|
|
108
|
+
url: normalized.repository?.contentRepository?.url ?? null,
|
|
109
|
+
defaultBranch: normalized.repository?.contentRepository?.defaultBranch ?? "main",
|
|
110
|
+
create: !normalized.repository?.contentRepository?.url
|
|
111
|
+
}
|
|
112
|
+
]
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function planKnowledgeHubLaunch(input, host) {
|
|
116
|
+
const intent = normalizeKnowledgeHubLaunchIntent(input);
|
|
117
|
+
return {
|
|
118
|
+
intent,
|
|
119
|
+
repository: planKnowledgeHubRepositories(intent, host),
|
|
120
|
+
contentResolution: intent.contentResolution ?? defaultHubContentResolutionPolicy(),
|
|
121
|
+
phases: [
|
|
122
|
+
{ phase: "launch_queued", status: "queued", title: "Launch queued" },
|
|
123
|
+
{ phase: "preflight_running", status: "queued", title: "Validating launch plan" },
|
|
124
|
+
{ phase: "repository_create", status: "queued", title: "Creating software repository" },
|
|
125
|
+
{ phase: "content_repository_create", status: "queued", title: "Creating content repository" },
|
|
126
|
+
{ phase: "starting_shape_apply", status: "queued", title: "Applying starting shape" },
|
|
127
|
+
{ phase: "config_sync", status: "queued", title: "Configuring runtime" },
|
|
128
|
+
{ phase: "cloudflare_reconcile", status: "queued", title: "Reconciling Cloudflare resources" },
|
|
129
|
+
{ phase: "backend_processing_connect", status: "queued", title: "Connecting backend processing" },
|
|
130
|
+
{ phase: "verification", status: "queued", title: "Verifying launch" },
|
|
131
|
+
{ phase: "packaging", status: "queued", title: "Packaging launch outputs" }
|
|
132
|
+
]
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
function validateRepositoryHost(host) {
|
|
136
|
+
const issues = [];
|
|
137
|
+
if (host.provider !== "github") issues.push("Repository Host provider must be github.");
|
|
138
|
+
if (!host.organizationOrOwner?.trim()) issues.push("Repository Host requires organizationOrOwner.");
|
|
139
|
+
if (!["treeseed_managed", "team_owned"].includes(host.ownership)) issues.push("Repository Host ownership must be treeseed_managed or team_owned.");
|
|
140
|
+
if (!host.name?.trim()) issues.push("Repository Host requires name.");
|
|
141
|
+
return {
|
|
142
|
+
ok: issues.length === 0,
|
|
143
|
+
issues,
|
|
144
|
+
host: {
|
|
145
|
+
...host,
|
|
146
|
+
defaultVisibility: host.defaultVisibility ?? "private",
|
|
147
|
+
softwareRepositoryNameTemplate: host.softwareRepositoryNameTemplate ?? "{hub}-site",
|
|
148
|
+
contentRepositoryNameTemplate: host.contentRepositoryNameTemplate ?? "{hub}-content",
|
|
149
|
+
branchPolicy: host.branchPolicy ?? {},
|
|
150
|
+
workflowPolicy: host.workflowPolicy ?? {},
|
|
151
|
+
allowedProjectKinds: host.allowedProjectKinds ?? ["knowledge_hub"],
|
|
152
|
+
status: host.status ?? "active"
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
async function createKnowledgeHubRepositories(input) {
|
|
157
|
+
const githubToken = process.env.TREESEED_HOSTED_HUBS_GITHUB_TOKEN || process.env.TREESEED_REPOSITORY_HOST_GITHUB_TOKEN || process.env.GH_TOKEN || process.env.GITHUB_TOKEN || "";
|
|
158
|
+
const githubEnv = githubToken ? { ...process.env, GH_TOKEN: githubToken, GITHUB_TOKEN: githubToken } : process.env;
|
|
159
|
+
const created = [];
|
|
160
|
+
for (const repository of input.plan.repositories) {
|
|
161
|
+
if (!repository.create || input.dryRun !== false) {
|
|
162
|
+
created.push({ ...repository, status: repository.create ? "planned" : "connected" });
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
const result = await createGitHubRepository({
|
|
166
|
+
owner: repository.owner,
|
|
167
|
+
name: repository.name,
|
|
168
|
+
description: input.description ?? `TreeSeed Knowledge Hub ${repository.role} repository`,
|
|
169
|
+
visibility: input.plan.visibility,
|
|
170
|
+
homepageUrl: input.homepageUrl ?? void 0,
|
|
171
|
+
topics: ["treeseed", "knowledge-hub", repository.role]
|
|
172
|
+
}, { env: githubEnv });
|
|
173
|
+
created.push({
|
|
174
|
+
...repository,
|
|
175
|
+
owner: result.owner,
|
|
176
|
+
name: result.name,
|
|
177
|
+
url: result.url,
|
|
178
|
+
status: "created"
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
return { repositories: created };
|
|
182
|
+
}
|
|
183
|
+
function providerLaunchInputFromIntent(plan) {
|
|
184
|
+
const intent = plan.intent;
|
|
185
|
+
const sourceKind = normalizeKnowledgeHubSourceKind(intent.source?.kind);
|
|
186
|
+
const software = plan.repository.repositories.find((repository) => repository.role === "software");
|
|
187
|
+
const content = plan.repository.repositories.find((repository) => repository.role === "content");
|
|
188
|
+
const providerInput = intent.execution?.providerLaunchInput ?? {};
|
|
189
|
+
return {
|
|
190
|
+
...providerInput,
|
|
191
|
+
projectId: providerInput.projectId ?? intent.hub.id ?? intent.hub.slug,
|
|
192
|
+
teamId: intent.team.id,
|
|
193
|
+
teamSlug: intent.team.slug ?? null,
|
|
194
|
+
projectSlug: intent.hub.slug,
|
|
195
|
+
projectName: intent.hub.name,
|
|
196
|
+
summary: intent.hub.purpose ?? null,
|
|
197
|
+
sourceKind: sourceKind === "blank_hub" ? "blank" : sourceKind === "market_listing" ? "template" : sourceKind,
|
|
198
|
+
sourceRef: intent.source?.ref ?? null,
|
|
199
|
+
hostingMode: intent.hosting?.mode === "treeseed_managed" ? "managed" : intent.hosting?.mode ?? "managed",
|
|
200
|
+
publicSite: intent.hub.visibility === "public",
|
|
201
|
+
repoOwner: providerInput.repoOwner ?? software?.owner ?? plan.repository.owner,
|
|
202
|
+
repoName: providerInput.repoName ?? software?.name ?? intent.hub.slug,
|
|
203
|
+
repoVisibility: plan.repository.visibility,
|
|
204
|
+
existingRepository: software?.url ? {
|
|
205
|
+
owner: software.owner,
|
|
206
|
+
name: software.name,
|
|
207
|
+
url: software.url,
|
|
208
|
+
defaultBranch: software.defaultBranch ?? "main",
|
|
209
|
+
visibility: plan.repository.visibility
|
|
210
|
+
} : null,
|
|
211
|
+
contentRepository: content ? {
|
|
212
|
+
owner: content.owner,
|
|
213
|
+
name: content.name,
|
|
214
|
+
url: content.url ?? null,
|
|
215
|
+
visibility: plan.repository.visibility,
|
|
216
|
+
defaultBranch: content.defaultBranch ?? "main"
|
|
217
|
+
} : null
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
function phaseFromProviderLaunch(entry) {
|
|
221
|
+
const completed = entry.status === "completed";
|
|
222
|
+
const canonicalPhase = {
|
|
223
|
+
repo_provision: "repository_create",
|
|
224
|
+
content_repository: "content_repository_create",
|
|
225
|
+
content_bootstrap: "starting_shape_apply",
|
|
226
|
+
workflow_bootstrap: "config_sync",
|
|
227
|
+
hosting_registration: "cloudflare_reconcile",
|
|
228
|
+
runtime_connection: "backend_processing_connect"
|
|
229
|
+
}[entry.phase] ?? entry.phase;
|
|
230
|
+
return {
|
|
231
|
+
phase: canonicalPhase,
|
|
232
|
+
status: entry.status,
|
|
233
|
+
title: canonicalPhase.replace(/_/gu, " "),
|
|
234
|
+
summary: entry.detail,
|
|
235
|
+
startedAt: completed ? null : entry.timestamp,
|
|
236
|
+
finishedAt: completed ? entry.timestamp : null,
|
|
237
|
+
data: { providerPhase: entry.phase },
|
|
238
|
+
error: entry.status === "failed" ? { message: entry.detail } : null
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
async function executeKnowledgeHubLaunch(input, options = {}) {
|
|
242
|
+
const plan = planKnowledgeHubLaunch(input);
|
|
243
|
+
const phases = [];
|
|
244
|
+
const providerLaunch = await executeKnowledgeHubProviderLaunch(providerLaunchInputFromIntent(plan), {
|
|
245
|
+
onPhase: async (providerPhase) => {
|
|
246
|
+
const phase = phaseFromProviderLaunch(providerPhase);
|
|
247
|
+
phases.push(phase);
|
|
248
|
+
await options?.onPhase?.(phase);
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
if (phases.length === 0) {
|
|
252
|
+
phases.push(...providerLaunch.phases.map(phaseFromProviderLaunch));
|
|
253
|
+
}
|
|
254
|
+
return {
|
|
255
|
+
intent: plan.intent,
|
|
256
|
+
plan,
|
|
257
|
+
repositories: plan.repository.repositories.map((repository) => {
|
|
258
|
+
if (repository.role === "content" && providerLaunch.contentRepository) {
|
|
259
|
+
return {
|
|
260
|
+
...repository,
|
|
261
|
+
owner: providerLaunch.contentRepository.owner,
|
|
262
|
+
name: providerLaunch.contentRepository.name,
|
|
263
|
+
url: providerLaunch.contentRepository.url,
|
|
264
|
+
defaultBranch: providerLaunch.contentRepository.defaultBranch,
|
|
265
|
+
create: false
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
if (repository.role !== "software") return repository;
|
|
269
|
+
return {
|
|
270
|
+
...repository,
|
|
271
|
+
owner: providerLaunch.repository.owner,
|
|
272
|
+
name: providerLaunch.repository.name,
|
|
273
|
+
url: providerLaunch.repository.url,
|
|
274
|
+
defaultBranch: providerLaunch.repository.defaultBranch,
|
|
275
|
+
create: false
|
|
276
|
+
};
|
|
277
|
+
}),
|
|
278
|
+
workingRoot: providerLaunch.workingRoot,
|
|
279
|
+
repository: providerLaunch.repository,
|
|
280
|
+
contentRepository: providerLaunch.contentRepository,
|
|
281
|
+
contentRepositoryWorkingRoot: providerLaunch.contentRepositoryWorkingRoot,
|
|
282
|
+
workflows: providerLaunch.workflows,
|
|
283
|
+
cloudflare: providerLaunch.cloudflare,
|
|
284
|
+
railway: providerLaunch.railway,
|
|
285
|
+
projectApiBaseUrl: providerLaunch.projectApiBaseUrl,
|
|
286
|
+
projectSiteUrl: providerLaunch.projectSiteUrl,
|
|
287
|
+
projectMetadata: providerLaunch.projectMetadata,
|
|
288
|
+
defaultWorkstream: providerLaunch.defaultWorkstream,
|
|
289
|
+
phases,
|
|
290
|
+
templatePackage: providerLaunch.templatePackage,
|
|
291
|
+
knowledgePackPackage: providerLaunch.knowledgePackPackage,
|
|
292
|
+
metadata: {
|
|
293
|
+
repositoryTopology: plan.repository.topology,
|
|
294
|
+
contentResolution: plan.contentResolution
|
|
295
|
+
}
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
export {
|
|
299
|
+
createKnowledgeHubRepositories,
|
|
300
|
+
defaultHubContentResolutionPolicy,
|
|
301
|
+
executeKnowledgeHubLaunch,
|
|
302
|
+
normalizeKnowledgeHubLaunchIntent,
|
|
303
|
+
normalizeKnowledgeHubSourceKind,
|
|
304
|
+
phaseFromProviderLaunch,
|
|
305
|
+
planKnowledgeHubLaunch,
|
|
306
|
+
planKnowledgeHubRepositories,
|
|
307
|
+
validateRepositoryHost
|
|
308
|
+
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { checkTreeseedProviderConnections, syncTreeseedGitHubEnvironment } from './config-runtime.ts';
|
|
2
2
|
import { configuredRailwayServices, deployRailwayService, ensureRailwayScheduledJobs, verifyRailwayScheduledJobs } from './railway-deploy.ts';
|
|
3
3
|
import { buildKnowledgeCoopKnowledgePackPackage, buildKnowledgeCoopTemplatePackage } from './knowledge-coop-packaging.ts';
|
|
4
|
-
export type
|
|
5
|
-
export interface
|
|
4
|
+
export type KnowledgeHubProviderLaunchFailurePhase = 'repo_provision_failed' | 'content_bootstrap_failed' | 'workflow_bootstrap_failed' | 'hosting_registration_failed' | 'runtime_connection_failed';
|
|
5
|
+
export interface KnowledgeHubProviderLaunchInput {
|
|
6
6
|
projectId: string;
|
|
7
7
|
teamId: string;
|
|
8
8
|
teamSlug?: string | null;
|
|
@@ -14,16 +14,33 @@ export interface KnowledgeCoopManagedLaunchInput {
|
|
|
14
14
|
hostingMode?: 'managed' | 'hybrid' | 'self_hosted';
|
|
15
15
|
publicSite?: boolean;
|
|
16
16
|
repoOwner?: string | null;
|
|
17
|
+
repoName?: string | null;
|
|
17
18
|
repoVisibility?: 'private' | 'public' | 'internal';
|
|
19
|
+
existingRepository?: {
|
|
20
|
+
owner: string;
|
|
21
|
+
name: string;
|
|
22
|
+
url: string;
|
|
23
|
+
defaultBranch?: string | null;
|
|
24
|
+
stagingBranch?: string | null;
|
|
25
|
+
visibility?: 'private' | 'public' | 'internal';
|
|
26
|
+
} | null;
|
|
27
|
+
contentRepository?: {
|
|
28
|
+
owner?: string | null;
|
|
29
|
+
name: string;
|
|
30
|
+
url?: string | null;
|
|
31
|
+
visibility?: 'private' | 'public' | 'internal';
|
|
32
|
+
defaultBranch?: string | null;
|
|
33
|
+
stagingBranch?: string | null;
|
|
34
|
+
} | null;
|
|
18
35
|
marketBaseUrl?: string | null;
|
|
19
36
|
projectApiBaseUrl?: string | null;
|
|
20
37
|
contactEmail?: string | null;
|
|
21
38
|
enableDefaultAgents?: boolean;
|
|
22
39
|
preserveWorkingTree?: boolean;
|
|
23
|
-
cloudflareHost?:
|
|
24
|
-
processingHost?:
|
|
40
|
+
cloudflareHost?: KnowledgeHubCloudflareHostLaunchInput | null;
|
|
41
|
+
processingHost?: KnowledgeHubProcessingHostLaunchInput | null;
|
|
25
42
|
}
|
|
26
|
-
export interface
|
|
43
|
+
export interface KnowledgeHubCloudflareHostConfig {
|
|
27
44
|
CLOUDFLARE_API_TOKEN?: string;
|
|
28
45
|
CLOUDFLARE_ACCOUNT_ID?: string;
|
|
29
46
|
TREESEED_CLOUDFLARE_PAGES_PROJECT_NAME?: string;
|
|
@@ -35,13 +52,13 @@ export interface KnowledgeCoopCloudflareHostConfig {
|
|
|
35
52
|
environments?: Partial<Record<'staging' | 'prod', Record<string, unknown>>>;
|
|
36
53
|
[key: string]: unknown;
|
|
37
54
|
}
|
|
38
|
-
export interface
|
|
55
|
+
export interface KnowledgeHubCloudflareHostLaunchInput {
|
|
39
56
|
mode: 'team_owned' | 'treeseed_managed';
|
|
40
57
|
hostId?: string | null;
|
|
41
58
|
targetEnvironments?: Array<'local' | 'staging' | 'prod'>;
|
|
42
|
-
config?:
|
|
59
|
+
config?: KnowledgeHubCloudflareHostConfig | null;
|
|
43
60
|
}
|
|
44
|
-
export interface
|
|
61
|
+
export interface KnowledgeHubProcessingHostConfig {
|
|
45
62
|
RAILWAY_API_TOKEN?: string;
|
|
46
63
|
TREESEED_RAILWAY_WORKSPACE?: string;
|
|
47
64
|
TREESEED_RAILWAY_API_URL?: string;
|
|
@@ -49,19 +66,19 @@ export interface KnowledgeCoopProcessingHostConfig {
|
|
|
49
66
|
environments?: Partial<Record<'staging' | 'prod', Record<string, unknown>>>;
|
|
50
67
|
[key: string]: unknown;
|
|
51
68
|
}
|
|
52
|
-
export interface
|
|
69
|
+
export interface KnowledgeHubProcessingHostLaunchInput {
|
|
53
70
|
mode: 'team_owned' | 'treeseed_managed';
|
|
54
71
|
hostId?: string | null;
|
|
55
72
|
targetEnvironments?: Array<'local' | 'staging' | 'prod'>;
|
|
56
|
-
config?:
|
|
73
|
+
config?: KnowledgeHubProcessingHostConfig | null;
|
|
57
74
|
}
|
|
58
|
-
export interface
|
|
75
|
+
export interface KnowledgeHubProviderLaunchPhaseRecord {
|
|
59
76
|
phase: string;
|
|
60
77
|
status: 'running' | 'completed' | 'failed';
|
|
61
78
|
detail: string;
|
|
62
79
|
timestamp: string;
|
|
63
80
|
}
|
|
64
|
-
export interface
|
|
81
|
+
export interface KnowledgeHubProviderLaunchResult {
|
|
65
82
|
workingRoot: string;
|
|
66
83
|
repository: {
|
|
67
84
|
slug: string;
|
|
@@ -72,6 +89,16 @@ export interface KnowledgeCoopManagedLaunchResult {
|
|
|
72
89
|
stagingBranch: string | null;
|
|
73
90
|
visibility: 'private' | 'public' | 'internal';
|
|
74
91
|
};
|
|
92
|
+
contentRepository?: {
|
|
93
|
+
slug: string;
|
|
94
|
+
owner: string;
|
|
95
|
+
name: string;
|
|
96
|
+
url: string;
|
|
97
|
+
defaultBranch: string;
|
|
98
|
+
stagingBranch: string | null;
|
|
99
|
+
visibility: 'private' | 'public' | 'internal';
|
|
100
|
+
} | null;
|
|
101
|
+
contentRepositoryWorkingRoot?: string | null;
|
|
75
102
|
workflows: {
|
|
76
103
|
repository: string | null;
|
|
77
104
|
workflows: Array<{
|
|
@@ -105,11 +132,11 @@ export interface KnowledgeCoopManagedLaunchResult {
|
|
|
105
132
|
projectSiteUrl: string;
|
|
106
133
|
projectMetadata: Record<string, unknown>;
|
|
107
134
|
defaultWorkstream: Record<string, unknown>;
|
|
108
|
-
phases:
|
|
135
|
+
phases: KnowledgeHubProviderLaunchPhaseRecord[];
|
|
109
136
|
templatePackage: ReturnType<typeof buildKnowledgeCoopTemplatePackage>;
|
|
110
137
|
knowledgePackPackage: ReturnType<typeof buildKnowledgeCoopKnowledgePackPackage>;
|
|
111
138
|
}
|
|
112
|
-
export interface
|
|
139
|
+
export interface KnowledgeHubProviderLaunchPreflightReport {
|
|
113
140
|
ok: boolean;
|
|
114
141
|
missingConfig: string[];
|
|
115
142
|
providerChecks: ReturnType<typeof checkTreeseedProviderConnections>;
|
|
@@ -120,7 +147,10 @@ export interface KnowledgeCoopLaunchPreflightReport {
|
|
|
120
147
|
railway: boolean;
|
|
121
148
|
};
|
|
122
149
|
}
|
|
123
|
-
export
|
|
150
|
+
export type KnowledgeHubProviderLaunchPhaseReporter = (phase: KnowledgeHubProviderLaunchPhaseRecord) => void | Promise<void>;
|
|
151
|
+
export declare function validateKnowledgeHubProviderLaunchPrerequisites(tenantRoot?: string, { valuesOverlay }?: {
|
|
124
152
|
valuesOverlay?: Record<string, string | undefined>;
|
|
125
|
-
}): Promise<
|
|
126
|
-
export declare function
|
|
153
|
+
}): Promise<KnowledgeHubProviderLaunchPreflightReport>;
|
|
154
|
+
export declare function executeKnowledgeHubProviderLaunch(input: KnowledgeHubProviderLaunchInput, options?: {
|
|
155
|
+
onPhase?: KnowledgeHubProviderLaunchPhaseReporter;
|
|
156
|
+
}): Promise<KnowledgeHubProviderLaunchResult>;
|