@treeseed/core 0.1.2 → 0.3.2
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 +11 -2
- package/dist/config.d.ts +1 -0
- package/dist/content-config.d.ts +10 -0
- package/dist/content.js +44 -10
- package/dist/contracts.d.ts +1 -130
- package/dist/deploy/config.js +4 -148
- package/dist/deploy/runtime.js +12 -65
- package/dist/env.yaml +86 -14
- package/dist/environment.d.ts +2 -130
- package/dist/environment.js +13 -311
- package/dist/index.js +2 -0
- package/dist/plugins/builtin/default-plugin.js +5 -0
- package/dist/plugins/constants.js +5 -23
- package/dist/plugins/plugin.d.ts +2 -42
- package/dist/plugins/plugin.js +1 -3
- package/dist/plugins/runtime.d.ts +2 -31
- package/dist/plugins/runtime.js +7 -117
- package/dist/scripts/build-dist.js +5 -1
- package/dist/scripts/release-verify.js +1 -2
- package/dist/scripts/run-fixture-astro-command.js +16 -0
- package/dist/scripts/test-smoke.js +14 -3
- package/dist/scripts/workspace-bootstrap.js +153 -0
- package/dist/tenant/config.js +8 -116
- package/dist/utils/agents/contracts/messages.d.ts +1 -88
- package/dist/utils/agents/contracts/messages.js +1 -138
- package/dist/utils/agents/contracts/run.d.ts +1 -20
- package/dist/utils/agents/contracts/run.js +1 -0
- package/dist/utils/agents/runtime-types.d.ts +1 -117
- package/dist/utils/agents/runtime-types.js +1 -4
- package/dist/utils/books-data.js +7 -75
- package/dist/utils/site-config-schema.js +1 -282
- package/package.json +12 -5
- package/templates/github/deploy.workflow.yml +1 -1
- package/dist/deploy/config.d.ts +0 -4
- package/dist/plugins/builtin/default-plugin.d.ts +0 -21
- package/dist/plugins/constants.d.ts +0 -21
- package/dist/tenant/config.d.ts +0 -9
|
@@ -1,138 +1 @@
|
|
|
1
|
-
|
|
2
|
-
"question_priority_updated",
|
|
3
|
-
"objective_priority_updated",
|
|
4
|
-
"architecture_updated",
|
|
5
|
-
"subscriber_notified",
|
|
6
|
-
"research_started",
|
|
7
|
-
"research_completed",
|
|
8
|
-
"task_complete",
|
|
9
|
-
"task_waiting",
|
|
10
|
-
"task_failed",
|
|
11
|
-
"task_verified",
|
|
12
|
-
"review_failed",
|
|
13
|
-
"review_waiting",
|
|
14
|
-
"release_started",
|
|
15
|
-
"release_completed",
|
|
16
|
-
"release_failed"
|
|
17
|
-
];
|
|
18
|
-
function ensureString(value, label) {
|
|
19
|
-
if (typeof value !== "string" || value.trim().length === 0) {
|
|
20
|
-
throw new Error(`Invalid ${label}: expected non-empty string.`);
|
|
21
|
-
}
|
|
22
|
-
return value;
|
|
23
|
-
}
|
|
24
|
-
function ensureOptionalString(value, label) {
|
|
25
|
-
if (value === null || value === void 0) {
|
|
26
|
-
return null;
|
|
27
|
-
}
|
|
28
|
-
return ensureString(value, label);
|
|
29
|
-
}
|
|
30
|
-
function ensureStringArray(value, label) {
|
|
31
|
-
if (!Array.isArray(value)) {
|
|
32
|
-
throw new Error(`Invalid ${label}: expected array.`);
|
|
33
|
-
}
|
|
34
|
-
return value.map((entry, index) => ensureString(entry, `${label}[${index}]`));
|
|
35
|
-
}
|
|
36
|
-
function ensureNumber(value, label) {
|
|
37
|
-
if (typeof value !== "number" || Number.isNaN(value)) {
|
|
38
|
-
throw new Error(`Invalid ${label}: expected number.`);
|
|
39
|
-
}
|
|
40
|
-
return value;
|
|
41
|
-
}
|
|
42
|
-
function parseAgentMessagePayload(type, payloadJson) {
|
|
43
|
-
const parsed = JSON.parse(payloadJson);
|
|
44
|
-
switch (type) {
|
|
45
|
-
case "question_priority_updated":
|
|
46
|
-
return {
|
|
47
|
-
questionId: ensureString(parsed.questionId, "questionId"),
|
|
48
|
-
reason: ensureString(parsed.reason, "reason"),
|
|
49
|
-
plannerRunId: ensureString(parsed.plannerRunId, "plannerRunId")
|
|
50
|
-
};
|
|
51
|
-
case "objective_priority_updated":
|
|
52
|
-
return {
|
|
53
|
-
objectiveId: ensureString(parsed.objectiveId, "objectiveId"),
|
|
54
|
-
reason: ensureString(parsed.reason, "reason"),
|
|
55
|
-
plannerRunId: ensureString(parsed.plannerRunId, "plannerRunId")
|
|
56
|
-
};
|
|
57
|
-
case "architecture_updated":
|
|
58
|
-
return {
|
|
59
|
-
objectiveId: ensureString(parsed.objectiveId, "objectiveId"),
|
|
60
|
-
knowledgeId: ensureString(parsed.knowledgeId, "knowledgeId"),
|
|
61
|
-
architectRunId: ensureString(parsed.architectRunId, "architectRunId")
|
|
62
|
-
};
|
|
63
|
-
case "subscriber_notified":
|
|
64
|
-
return {
|
|
65
|
-
email: ensureString(parsed.email, "email"),
|
|
66
|
-
itemCount: ensureNumber(parsed.itemCount, "itemCount"),
|
|
67
|
-
notifierRunId: ensureString(parsed.notifierRunId, "notifierRunId")
|
|
68
|
-
};
|
|
69
|
-
case "research_started":
|
|
70
|
-
return {
|
|
71
|
-
questionId: ensureString(parsed.questionId, "questionId"),
|
|
72
|
-
researcherRunId: ensureString(parsed.researcherRunId, "researcherRunId")
|
|
73
|
-
};
|
|
74
|
-
case "research_completed":
|
|
75
|
-
return {
|
|
76
|
-
questionId: ensureString(parsed.questionId, "questionId"),
|
|
77
|
-
knowledgeId: ensureOptionalString(parsed.knowledgeId, "knowledgeId"),
|
|
78
|
-
researcherRunId: ensureString(parsed.researcherRunId, "researcherRunId")
|
|
79
|
-
};
|
|
80
|
-
case "task_complete":
|
|
81
|
-
return {
|
|
82
|
-
branchName: ensureOptionalString(parsed.branchName, "branchName"),
|
|
83
|
-
changedTargets: ensureStringArray(parsed.changedTargets, "changedTargets"),
|
|
84
|
-
engineerRunId: ensureString(parsed.engineerRunId, "engineerRunId")
|
|
85
|
-
};
|
|
86
|
-
case "task_waiting":
|
|
87
|
-
return {
|
|
88
|
-
blockingReason: ensureString(parsed.blockingReason, "blockingReason"),
|
|
89
|
-
engineerRunId: ensureString(parsed.engineerRunId, "engineerRunId")
|
|
90
|
-
};
|
|
91
|
-
case "task_failed":
|
|
92
|
-
return {
|
|
93
|
-
failureSummary: ensureString(parsed.failureSummary, "failureSummary"),
|
|
94
|
-
engineerRunId: ensureString(parsed.engineerRunId, "engineerRunId")
|
|
95
|
-
};
|
|
96
|
-
case "task_verified":
|
|
97
|
-
return {
|
|
98
|
-
branchName: ensureOptionalString(parsed.branchName, "branchName"),
|
|
99
|
-
reviewerRunId: ensureString(parsed.reviewerRunId, "reviewerRunId")
|
|
100
|
-
};
|
|
101
|
-
case "review_failed":
|
|
102
|
-
return {
|
|
103
|
-
failureSummary: ensureString(parsed.failureSummary, "failureSummary"),
|
|
104
|
-
reviewerRunId: ensureString(parsed.reviewerRunId, "reviewerRunId")
|
|
105
|
-
};
|
|
106
|
-
case "review_waiting":
|
|
107
|
-
return {
|
|
108
|
-
blockingReason: ensureString(parsed.blockingReason, "blockingReason"),
|
|
109
|
-
reviewerRunId: ensureString(parsed.reviewerRunId, "reviewerRunId")
|
|
110
|
-
};
|
|
111
|
-
case "release_started":
|
|
112
|
-
return {
|
|
113
|
-
taskRunId: ensureOptionalString(parsed.taskRunId, "taskRunId"),
|
|
114
|
-
releaserRunId: ensureString(parsed.releaserRunId, "releaserRunId")
|
|
115
|
-
};
|
|
116
|
-
case "release_completed":
|
|
117
|
-
return {
|
|
118
|
-
releaseSummary: ensureString(parsed.releaseSummary, "releaseSummary"),
|
|
119
|
-
releaserRunId: ensureString(parsed.releaserRunId, "releaserRunId")
|
|
120
|
-
};
|
|
121
|
-
case "release_failed":
|
|
122
|
-
return {
|
|
123
|
-
failureSummary: ensureString(parsed.failureSummary, "failureSummary"),
|
|
124
|
-
releaserRunId: ensureString(parsed.releaserRunId, "releaserRunId")
|
|
125
|
-
};
|
|
126
|
-
default:
|
|
127
|
-
throw new Error(`Unsupported message type "${type}".`);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
function serializeAgentMessagePayload(type, payload) {
|
|
131
|
-
parseAgentMessagePayload(type, JSON.stringify(payload));
|
|
132
|
-
return payload;
|
|
133
|
-
}
|
|
134
|
-
export {
|
|
135
|
-
AGENT_MESSAGE_TYPES,
|
|
136
|
-
parseAgentMessagePayload,
|
|
137
|
-
serializeAgentMessagePayload
|
|
138
|
-
};
|
|
1
|
+
export * from "@treeseed/sdk/utils/agents/contracts/messages";
|
|
@@ -1,20 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
export interface AgentRunTrace {
|
|
3
|
-
[key: string]: unknown;
|
|
4
|
-
runId: string;
|
|
5
|
-
agentSlug: string;
|
|
6
|
-
handlerKind: string;
|
|
7
|
-
triggerKind: string;
|
|
8
|
-
triggerSource: string;
|
|
9
|
-
claimedMessageId: number | null;
|
|
10
|
-
selectedItemKey: string | null;
|
|
11
|
-
branchName: string | null;
|
|
12
|
-
commitSha: string | null;
|
|
13
|
-
changedPaths: string[];
|
|
14
|
-
summary: string | null;
|
|
15
|
-
error: string | null;
|
|
16
|
-
errorCategory: AgentErrorCategory | null;
|
|
17
|
-
startedAt: string;
|
|
18
|
-
finishedAt: string | null;
|
|
19
|
-
status: string;
|
|
20
|
-
}
|
|
1
|
+
export * from '@treeseed/sdk/utils/agents/contracts/run';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@treeseed/sdk/utils/agents/contracts/run";
|
|
@@ -1,117 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import type { AgentErrorCategory } from './contracts/run.ts';
|
|
3
|
-
import type { ScopedAgentSdk, SdkMessageEntity } from '@treeseed/sdk';
|
|
4
|
-
export interface AgentTriggerInvocation {
|
|
5
|
-
kind: 'startup' | 'schedule' | 'message' | 'manual' | 'follow';
|
|
6
|
-
source: string;
|
|
7
|
-
trigger: AgentTriggerConfig;
|
|
8
|
-
message?: SdkMessageEntity | null;
|
|
9
|
-
followModels?: string[];
|
|
10
|
-
cursorValue?: string | null;
|
|
11
|
-
}
|
|
12
|
-
export interface AgentExecutionResult {
|
|
13
|
-
status: AgentRunStatus;
|
|
14
|
-
summary: string;
|
|
15
|
-
stdout?: string;
|
|
16
|
-
stderr?: string;
|
|
17
|
-
errorCategory?: AgentErrorCategory | null;
|
|
18
|
-
metadata?: Record<string, unknown>;
|
|
19
|
-
}
|
|
20
|
-
export interface AgentMutationResult {
|
|
21
|
-
branchName: string | null;
|
|
22
|
-
commitMessage: string | null;
|
|
23
|
-
worktreePath: string | null;
|
|
24
|
-
commitSha: string | null;
|
|
25
|
-
changedPaths: string[];
|
|
26
|
-
}
|
|
27
|
-
export interface AgentRepositoryInspectionResult {
|
|
28
|
-
branchName: string | null;
|
|
29
|
-
changedPaths: string[];
|
|
30
|
-
commitSha: string | null;
|
|
31
|
-
summary: string;
|
|
32
|
-
}
|
|
33
|
-
export interface AgentVerificationResult {
|
|
34
|
-
status: 'completed' | 'failed' | 'waiting';
|
|
35
|
-
summary: string;
|
|
36
|
-
stdout?: string;
|
|
37
|
-
stderr?: string;
|
|
38
|
-
errorCategory?: AgentErrorCategory | null;
|
|
39
|
-
}
|
|
40
|
-
export interface AgentNotificationResult {
|
|
41
|
-
status: 'completed' | 'failed' | 'waiting';
|
|
42
|
-
summary: string;
|
|
43
|
-
deliveredCount: number;
|
|
44
|
-
}
|
|
45
|
-
export interface AgentResearchResult {
|
|
46
|
-
status: 'completed' | 'failed' | 'waiting';
|
|
47
|
-
summary: string;
|
|
48
|
-
markdown: string;
|
|
49
|
-
sources?: string[];
|
|
50
|
-
errorCategory?: AgentErrorCategory | null;
|
|
51
|
-
}
|
|
52
|
-
export interface AgentExecutionAdapter {
|
|
53
|
-
runTask(input: {
|
|
54
|
-
agent: AgentRuntimeSpec;
|
|
55
|
-
runId: string;
|
|
56
|
-
prompt: string;
|
|
57
|
-
}): Promise<AgentExecutionResult>;
|
|
58
|
-
}
|
|
59
|
-
export interface AgentMutationAdapter {
|
|
60
|
-
writeArtifact(input: {
|
|
61
|
-
runId: string;
|
|
62
|
-
agent: AgentRuntimeSpec;
|
|
63
|
-
relativePath: string;
|
|
64
|
-
content: string;
|
|
65
|
-
commitMessage: string;
|
|
66
|
-
}): Promise<AgentMutationResult>;
|
|
67
|
-
}
|
|
68
|
-
export interface AgentRepositoryInspectionAdapter {
|
|
69
|
-
inspectBranch(input: {
|
|
70
|
-
repoRoot: string;
|
|
71
|
-
branchName: string | null;
|
|
72
|
-
}): Promise<AgentRepositoryInspectionResult>;
|
|
73
|
-
}
|
|
74
|
-
export interface AgentVerificationAdapter {
|
|
75
|
-
runChecks(input: {
|
|
76
|
-
agent: AgentRuntimeSpec;
|
|
77
|
-
runId: string;
|
|
78
|
-
commands: string[];
|
|
79
|
-
}): Promise<AgentVerificationResult>;
|
|
80
|
-
}
|
|
81
|
-
export interface AgentNotificationAdapter {
|
|
82
|
-
deliver(input: {
|
|
83
|
-
agent: AgentRuntimeSpec;
|
|
84
|
-
runId: string;
|
|
85
|
-
recipients: string[];
|
|
86
|
-
subject: string;
|
|
87
|
-
body: string;
|
|
88
|
-
}): Promise<AgentNotificationResult>;
|
|
89
|
-
}
|
|
90
|
-
export interface AgentResearchAdapter {
|
|
91
|
-
research(input: {
|
|
92
|
-
agent: AgentRuntimeSpec;
|
|
93
|
-
runId: string;
|
|
94
|
-
questionId: string;
|
|
95
|
-
reason: string | null;
|
|
96
|
-
}): Promise<AgentResearchResult>;
|
|
97
|
-
}
|
|
98
|
-
export interface AgentContext {
|
|
99
|
-
runId: string;
|
|
100
|
-
repoRoot: string;
|
|
101
|
-
agent: AgentRuntimeSpec;
|
|
102
|
-
sdk: ScopedAgentSdk;
|
|
103
|
-
trigger: AgentTriggerInvocation;
|
|
104
|
-
execution: AgentExecutionAdapter;
|
|
105
|
-
mutations: AgentMutationAdapter;
|
|
106
|
-
repository: AgentRepositoryInspectionAdapter;
|
|
107
|
-
verification: AgentVerificationAdapter;
|
|
108
|
-
notifications: AgentNotificationAdapter;
|
|
109
|
-
research: AgentResearchAdapter;
|
|
110
|
-
}
|
|
111
|
-
export interface AgentHandler<TInputs = unknown, TResult = unknown> {
|
|
112
|
-
kind: AgentHandlerKind;
|
|
113
|
-
resolveInputs(context: AgentContext): Promise<TInputs>;
|
|
114
|
-
execute(context: AgentContext, inputs: TInputs): Promise<TResult>;
|
|
115
|
-
emitOutputs(context: AgentContext, result: TResult): Promise<AgentExecutionResult>;
|
|
116
|
-
}
|
|
117
|
-
export declare const TRESEED_AGENT_RUNTIME_TYPES_MODULE = true;
|
|
1
|
+
export * from '@treeseed/sdk/utils/agents/runtime-types';
|
package/dist/utils/books-data.js
CHANGED
|
@@ -1,78 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
function collectMarkdownFiles(rootPath) {
|
|
10
|
-
const stats = statSync(rootPath);
|
|
11
|
-
if (stats.isFile()) {
|
|
12
|
-
return [rootPath];
|
|
13
|
-
}
|
|
14
|
-
return sortPaths(
|
|
15
|
-
readdirSync(rootPath, { withFileTypes: true }).flatMap((entry) => {
|
|
16
|
-
const fullPath = path.join(rootPath, entry.name);
|
|
17
|
-
if (entry.isDirectory()) {
|
|
18
|
-
return collectMarkdownFiles(fullPath);
|
|
19
|
-
}
|
|
20
|
-
if (entry.isFile() && (entry.name.endsWith(".md") || entry.name.endsWith(".mdx"))) {
|
|
21
|
-
return [fullPath];
|
|
22
|
-
}
|
|
23
|
-
return [];
|
|
24
|
-
})
|
|
25
|
-
);
|
|
26
|
-
}
|
|
27
|
-
function parseFrontmatter(filePath) {
|
|
28
|
-
const raw = readFileSync(filePath, "utf8");
|
|
29
|
-
const match = raw.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
30
|
-
if (!match) {
|
|
31
|
-
throw new Error(`Book content entry is missing frontmatter: ${filePath}`);
|
|
32
|
-
}
|
|
33
|
-
return parseYaml(match[1]);
|
|
34
|
-
}
|
|
35
|
-
function inferDocsLibraryDownload(book) {
|
|
36
|
-
const title = book?.title ? `${book.title} Library` : "Knowledge Library";
|
|
37
|
-
return {
|
|
38
|
-
downloadFileName: "treeseed-knowledge.md",
|
|
39
|
-
downloadHref: "/books/treeseed-knowledge.md",
|
|
40
|
-
downloadTitle: title
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
function buildTenantBookRuntime(tenantConfig, options = {}) {
|
|
44
|
-
const projectRoot = options.projectRoot ?? process.cwd();
|
|
45
|
-
const booksContentRoot = path.resolve(projectRoot, getTenantContentRoot(tenantConfig, "books"));
|
|
46
|
-
const books = collectMarkdownFiles(booksContentRoot).map((filePath) => {
|
|
47
|
-
const frontmatter = parseFrontmatter(filePath);
|
|
48
|
-
return {
|
|
49
|
-
...frontmatter,
|
|
50
|
-
id: path.basename(filePath, path.extname(filePath))
|
|
51
|
-
};
|
|
52
|
-
}).sort((left, right) => left.order - right.order);
|
|
53
|
-
const docsHomePath = options.docsHomePath ?? "/knowledge/";
|
|
54
|
-
const docsLibraryDownload = options.docsLibraryDownload ?? inferDocsLibraryDownload(tenantConfig);
|
|
55
|
-
return {
|
|
56
|
-
BOOKS: books,
|
|
57
|
-
BOOKS_LINK: {
|
|
58
|
-
label: "Books",
|
|
59
|
-
link: docsHomePath
|
|
60
|
-
},
|
|
61
|
-
TREESEED_LINKS: {
|
|
62
|
-
home: docsHomePath
|
|
63
|
-
},
|
|
64
|
-
TREESEED_LIBRARY_DOWNLOAD: docsLibraryDownload
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
const runtime = buildTenantBookRuntime(RUNTIME_TENANT, {
|
|
68
|
-
projectRoot: RUNTIME_PROJECT_ROOT,
|
|
69
|
-
docsLibraryDownload: {
|
|
70
|
-
downloadFileName: "treeseed-knowledge.md",
|
|
71
|
-
downloadHref: "/books/treeseed-knowledge.md",
|
|
72
|
-
downloadTitle: "TreeSeed Knowledge Library"
|
|
73
|
-
}
|
|
74
|
-
});
|
|
75
|
-
const { BOOKS, BOOKS_LINK, TREESEED_LINKS, TREESEED_LIBRARY_DOWNLOAD } = runtime;
|
|
1
|
+
import {
|
|
2
|
+
BOOKS,
|
|
3
|
+
BOOKS_LINK,
|
|
4
|
+
TREESEED_LIBRARY_DOWNLOAD,
|
|
5
|
+
TREESEED_LINKS,
|
|
6
|
+
buildTenantBookRuntime
|
|
7
|
+
} from "@treeseed/sdk/platform/books-data";
|
|
76
8
|
export {
|
|
77
9
|
BOOKS,
|
|
78
10
|
BOOKS_LINK,
|
|
@@ -1,282 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
function isRecord(value) {
|
|
4
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
function expectRecord(value, path) {
|
|
8
|
-
if (!isRecord(value)) {
|
|
9
|
-
throw new Error(`Expected ${path} to be an object.`);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
return value;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function expectString(value, path) {
|
|
16
|
-
if (typeof value !== 'string' || value.trim().length === 0) {
|
|
17
|
-
throw new Error(`Expected ${path} to be a non-empty string.`);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return value.trim();
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function optionalString(value, path) {
|
|
24
|
-
if (value === undefined || value === null || value === '') {
|
|
25
|
-
return undefined;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return expectString(value, path);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function optionalBoolean(value, path) {
|
|
32
|
-
if (value === undefined || value === null) {
|
|
33
|
-
return undefined;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
if (typeof value !== 'boolean') {
|
|
37
|
-
throw new Error(`Expected ${path} to be a boolean.`);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return value;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function optionalRecord(value, path) {
|
|
44
|
-
if (value === undefined || value === null) {
|
|
45
|
-
return undefined;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
return expectRecord(value, path);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function stringArray(value, path) {
|
|
52
|
-
if (value === undefined || value === null) {
|
|
53
|
-
return [];
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
if (!Array.isArray(value)) {
|
|
57
|
-
throw new Error(`Expected ${path} to be an array.`);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return value.map((entry, index) => expectString(entry, `${path}[${index}]`));
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function parseMenuGroups(value, path) {
|
|
64
|
-
if (!Array.isArray(value)) {
|
|
65
|
-
throw new Error(`Expected ${path} to be an array.`);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return value.map((group, groupIndex) => {
|
|
69
|
-
const parsedGroup = expectRecord(group, `${path}[${groupIndex}]`);
|
|
70
|
-
const items = parsedGroup.items;
|
|
71
|
-
if (!Array.isArray(items) || items.length === 0) {
|
|
72
|
-
throw new Error(`Expected ${path}[${groupIndex}].items to contain at least one menu item.`);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return {
|
|
76
|
-
label: expectString(parsedGroup.label, `${path}[${groupIndex}].label`),
|
|
77
|
-
items: items.map((item, itemIndex) => {
|
|
78
|
-
const parsedItem = expectRecord(item, `${path}[${groupIndex}].items[${itemIndex}]`);
|
|
79
|
-
return {
|
|
80
|
-
label: expectString(parsedItem.label, `${path}[${groupIndex}].items[${itemIndex}].label`),
|
|
81
|
-
href: expectString(parsedItem.href, `${path}[${groupIndex}].items[${itemIndex}].href`),
|
|
82
|
-
};
|
|
83
|
-
}),
|
|
84
|
-
};
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function parseContactRouting(value, path) {
|
|
89
|
-
const parsedValue = expectRecord(value ?? {}, path);
|
|
90
|
-
const keys = ['default', 'question', 'feedback', 'collaboration', 'issue'];
|
|
91
|
-
|
|
92
|
-
return Object.fromEntries(
|
|
93
|
-
keys.flatMap((key) => {
|
|
94
|
-
if (!(key in parsedValue)) {
|
|
95
|
-
return [];
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
return [[key, stringArray(parsedValue[key], `${path}.${key}`)]];
|
|
99
|
-
}),
|
|
100
|
-
);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
function parseTheme(value, path) {
|
|
104
|
-
const theme = optionalRecord(value, path);
|
|
105
|
-
if (!theme) {
|
|
106
|
-
return undefined;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
const surfaces = optionalRecord(theme.surfaces, `${path}.surfaces`);
|
|
110
|
-
const text = optionalRecord(theme.text, `${path}.text`);
|
|
111
|
-
const border = optionalRecord(theme.border, `${path}.border`);
|
|
112
|
-
const accent = optionalRecord(theme.accent, `${path}.accent`);
|
|
113
|
-
const info = optionalRecord(theme.info, `${path}.info`);
|
|
114
|
-
const warm = optionalRecord(theme.warm, `${path}.warm`);
|
|
115
|
-
|
|
116
|
-
return {
|
|
117
|
-
surfaces: surfaces
|
|
118
|
-
? {
|
|
119
|
-
background: optionalString(surfaces.background, `${path}.surfaces.background`),
|
|
120
|
-
backgroundElevated: optionalString(
|
|
121
|
-
surfaces.backgroundElevated,
|
|
122
|
-
`${path}.surfaces.backgroundElevated`,
|
|
123
|
-
),
|
|
124
|
-
backgroundSoft: optionalString(surfaces.backgroundSoft, `${path}.surfaces.backgroundSoft`),
|
|
125
|
-
panel: optionalString(surfaces.panel, `${path}.surfaces.panel`),
|
|
126
|
-
panelStrong: optionalString(surfaces.panelStrong, `${path}.surfaces.panelStrong`),
|
|
127
|
-
}
|
|
128
|
-
: undefined,
|
|
129
|
-
text: text
|
|
130
|
-
? {
|
|
131
|
-
body: optionalString(text.body, `${path}.text.body`),
|
|
132
|
-
muted: optionalString(text.muted, `${path}.text.muted`),
|
|
133
|
-
soft: optionalString(text.soft, `${path}.text.soft`),
|
|
134
|
-
}
|
|
135
|
-
: undefined,
|
|
136
|
-
border: border
|
|
137
|
-
? {
|
|
138
|
-
base: optionalString(border.base, `${path}.border.base`),
|
|
139
|
-
strong: optionalString(border.strong, `${path}.border.strong`),
|
|
140
|
-
grid: optionalString(border.grid, `${path}.border.grid`),
|
|
141
|
-
}
|
|
142
|
-
: undefined,
|
|
143
|
-
accent: accent
|
|
144
|
-
? {
|
|
145
|
-
base: optionalString(accent.base, `${path}.accent.base`),
|
|
146
|
-
strong: optionalString(accent.strong, `${path}.accent.strong`),
|
|
147
|
-
soft: optionalString(accent.soft, `${path}.accent.soft`),
|
|
148
|
-
}
|
|
149
|
-
: undefined,
|
|
150
|
-
info: info
|
|
151
|
-
? {
|
|
152
|
-
base: optionalString(info.base, `${path}.info.base`),
|
|
153
|
-
strong: optionalString(info.strong, `${path}.info.strong`),
|
|
154
|
-
soft: optionalString(info.soft, `${path}.info.soft`),
|
|
155
|
-
}
|
|
156
|
-
: undefined,
|
|
157
|
-
warm: warm
|
|
158
|
-
? {
|
|
159
|
-
base: optionalString(warm.base, `${path}.warm.base`),
|
|
160
|
-
strong: optionalString(warm.strong, `${path}.warm.strong`),
|
|
161
|
-
}
|
|
162
|
-
: undefined,
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* @param {string} source
|
|
168
|
-
*/
|
|
169
|
-
export function parseSiteConfig(source) {
|
|
170
|
-
const parsed = expectRecord(parseYaml(source), 'config');
|
|
171
|
-
const site = expectRecord(parsed.site, 'site');
|
|
172
|
-
const models = expectRecord(parsed.models ?? {}, 'models');
|
|
173
|
-
const pageModel = expectRecord(models.pages ?? {}, 'models.pages');
|
|
174
|
-
const noteModel = expectRecord(models.notes ?? {}, 'models.notes');
|
|
175
|
-
const questionModel = expectRecord(models.questions ?? {}, 'models.questions');
|
|
176
|
-
const objectiveModel = expectRecord(models.objectives ?? {}, 'models.objectives');
|
|
177
|
-
const peopleModel = expectRecord(models.people ?? {}, 'models.people');
|
|
178
|
-
const agentModel = expectRecord(models.agents ?? {}, 'models.agents');
|
|
179
|
-
const bookModel = expectRecord(models.books ?? {}, 'models.books');
|
|
180
|
-
const docsModel = expectRecord(models.docs ?? {}, 'models.docs');
|
|
181
|
-
const pageDefaults = expectRecord(pageModel.defaults ?? {}, 'models.pages.defaults');
|
|
182
|
-
const noteDefaults = expectRecord(noteModel.defaults ?? {}, 'models.notes.defaults');
|
|
183
|
-
const questionDefaults = expectRecord(questionModel.defaults ?? {}, 'models.questions.defaults');
|
|
184
|
-
const objectiveDefaults = expectRecord(objectiveModel.defaults ?? {}, 'models.objectives.defaults');
|
|
185
|
-
const peopleDefaults = expectRecord(peopleModel.defaults ?? {}, 'models.people.defaults');
|
|
186
|
-
const agentDefaults = expectRecord(agentModel.defaults ?? {}, 'models.agents.defaults');
|
|
187
|
-
const bookDefaults = expectRecord(bookModel.defaults ?? {}, 'models.books.defaults');
|
|
188
|
-
const docsDefaults = expectRecord(docsModel.defaults ?? {}, 'models.docs.defaults');
|
|
189
|
-
const logo = expectRecord(site.logo, 'site.logo');
|
|
190
|
-
const forms = expectRecord(site.forms ?? {}, 'site.forms');
|
|
191
|
-
const emailNotifications = expectRecord(site.emailNotifications, 'site.emailNotifications');
|
|
192
|
-
|
|
193
|
-
return {
|
|
194
|
-
site: {
|
|
195
|
-
logo: {
|
|
196
|
-
src: expectString(logo.src, 'site.logo.src'),
|
|
197
|
-
alt: expectString(logo.alt, 'site.logo.alt'),
|
|
198
|
-
},
|
|
199
|
-
name: expectString(site.name, 'site.name'),
|
|
200
|
-
statement: expectString(site.statement, 'site.statement'),
|
|
201
|
-
siteUrl: expectString(site.siteUrl, 'site.siteUrl'),
|
|
202
|
-
githubRepository: expectString(site.githubRepository, 'site.githubRepository'),
|
|
203
|
-
discordLink: expectString(site.discordLink, 'site.discordLink'),
|
|
204
|
-
headerMenu: parseMenuGroups(site.headerMenu, 'site.headerMenu'),
|
|
205
|
-
footerMenu: parseMenuGroups(site.footerMenu, 'site.footerMenu'),
|
|
206
|
-
forms: {
|
|
207
|
-
apiBaseUrl: optionalString(forms.apiBaseUrl, 'site.forms.apiBaseUrl'),
|
|
208
|
-
},
|
|
209
|
-
emailNotifications: {
|
|
210
|
-
contactRouting: parseContactRouting(
|
|
211
|
-
emailNotifications.contactRouting,
|
|
212
|
-
'site.emailNotifications.contactRouting',
|
|
213
|
-
),
|
|
214
|
-
subscribeRecipients: stringArray(
|
|
215
|
-
emailNotifications.subscribeRecipients,
|
|
216
|
-
'site.emailNotifications.subscribeRecipients',
|
|
217
|
-
),
|
|
218
|
-
},
|
|
219
|
-
summary: expectString(site.summary, 'site.summary'),
|
|
220
|
-
projectStage: expectString(site.projectStage, 'site.projectStage'),
|
|
221
|
-
projectStageDetail: expectString(site.projectStageDetail, 'site.projectStageDetail'),
|
|
222
|
-
theme: parseTheme(site.theme, 'site.theme'),
|
|
223
|
-
},
|
|
224
|
-
models: {
|
|
225
|
-
pages: {
|
|
226
|
-
defaults: {
|
|
227
|
-
pageLayout: optionalString(pageDefaults.pageLayout, 'models.pages.defaults.pageLayout'),
|
|
228
|
-
status: optionalString(pageDefaults.status, 'models.pages.defaults.status'),
|
|
229
|
-
stage: optionalString(pageDefaults.stage, 'models.pages.defaults.stage'),
|
|
230
|
-
audience: stringArray(pageDefaults.audience, 'models.pages.defaults.audience'),
|
|
231
|
-
},
|
|
232
|
-
},
|
|
233
|
-
notes: {
|
|
234
|
-
defaults: {
|
|
235
|
-
author: optionalString(noteDefaults.author, 'models.notes.defaults.author'),
|
|
236
|
-
draft: optionalBoolean(noteDefaults.draft, 'models.notes.defaults.draft'),
|
|
237
|
-
tags: stringArray(noteDefaults.tags, 'models.notes.defaults.tags'),
|
|
238
|
-
status: optionalString(noteDefaults.status, 'models.notes.defaults.status'),
|
|
239
|
-
},
|
|
240
|
-
},
|
|
241
|
-
questions: {
|
|
242
|
-
defaults: {
|
|
243
|
-
draft: optionalBoolean(questionDefaults.draft, 'models.questions.defaults.draft'),
|
|
244
|
-
tags: stringArray(questionDefaults.tags, 'models.questions.defaults.tags'),
|
|
245
|
-
status: optionalString(questionDefaults.status, 'models.questions.defaults.status'),
|
|
246
|
-
},
|
|
247
|
-
},
|
|
248
|
-
objectives: {
|
|
249
|
-
defaults: {
|
|
250
|
-
draft: optionalBoolean(objectiveDefaults.draft, 'models.objectives.defaults.draft'),
|
|
251
|
-
tags: stringArray(objectiveDefaults.tags, 'models.objectives.defaults.tags'),
|
|
252
|
-
status: optionalString(objectiveDefaults.status, 'models.objectives.defaults.status'),
|
|
253
|
-
},
|
|
254
|
-
},
|
|
255
|
-
people: {
|
|
256
|
-
defaults: {
|
|
257
|
-
status: optionalString(peopleDefaults.status, 'models.people.defaults.status'),
|
|
258
|
-
tags: stringArray(peopleDefaults.tags, 'models.people.defaults.tags'),
|
|
259
|
-
},
|
|
260
|
-
},
|
|
261
|
-
agents: {
|
|
262
|
-
defaults: {
|
|
263
|
-
tags: stringArray(agentDefaults.tags, 'models.agents.defaults.tags'),
|
|
264
|
-
runtimeStatus: optionalString(
|
|
265
|
-
agentDefaults.runtimeStatus,
|
|
266
|
-
'models.agents.defaults.runtimeStatus',
|
|
267
|
-
),
|
|
268
|
-
},
|
|
269
|
-
},
|
|
270
|
-
books: {
|
|
271
|
-
defaults: {
|
|
272
|
-
tags: stringArray(bookDefaults.tags, 'models.books.defaults.tags'),
|
|
273
|
-
},
|
|
274
|
-
},
|
|
275
|
-
docs: {
|
|
276
|
-
defaults: {
|
|
277
|
-
tags: stringArray(docsDefaults.tags, 'models.docs.defaults.tags'),
|
|
278
|
-
},
|
|
279
|
-
},
|
|
280
|
-
},
|
|
281
|
-
};
|
|
282
|
-
}
|
|
1
|
+
export { parseSiteConfig } from '@treeseed/sdk/platform/site-config-schema';
|