@treeseed/core 0.3.2 → 0.4.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.
Files changed (52) hide show
  1. package/README.md +16 -2
  2. package/dist/config.js +1 -1
  3. package/dist/content-config.js +1 -1
  4. package/dist/content.js +3 -3
  5. package/dist/index.js +1 -68
  6. package/dist/scripts/aggregate-book.js +1 -1
  7. package/dist/scripts/build-dist.js +3 -14
  8. package/dist/scripts/build-tenant-worker.js +2 -2
  9. package/dist/scripts/run-fixture-astro-command.js +216 -13
  10. package/dist/site-resources.d.ts +2 -2
  11. package/dist/site.js +3 -3
  12. package/dist/tenant/bridge.js +1 -1
  13. package/dist/tenant/runtime-config.js +1 -1
  14. package/dist/utils/forms/config.js +5 -1
  15. package/dist/utils/forms/provider-runtime.js +42 -0
  16. package/dist/utils/forms/service.js +2 -2
  17. package/dist/utils/starlight-nav.js +6 -1
  18. package/package.json +3 -37
  19. package/dist/agents/index.js +0 -5
  20. package/dist/agents/registry-helper.js +0 -14
  21. package/dist/agents/registry.js +0 -88
  22. package/dist/contracts.d.ts +0 -1
  23. package/dist/contracts.js +0 -0
  24. package/dist/deploy/config.js +0 -10
  25. package/dist/deploy/runtime.js +0 -24
  26. package/dist/environment.d.ts +0 -2
  27. package/dist/environment.js +0 -26
  28. package/dist/plugin-default.js +0 -4
  29. package/dist/plugins/builtin/default-plugin.js +0 -37
  30. package/dist/plugins/constants.js +0 -10
  31. package/dist/plugins/plugin.d.ts +0 -2
  32. package/dist/plugins/plugin.js +0 -4
  33. package/dist/plugins/runtime.d.ts +0 -2
  34. package/dist/plugins/runtime.js +0 -10
  35. package/dist/tenant/config.js +0 -16
  36. package/dist/types/agents.d.ts +0 -1
  37. package/dist/types/agents.js +0 -1
  38. package/dist/utils/agents/adapters/execution.js +0 -90
  39. package/dist/utils/agents/adapters/mutations.js +0 -30
  40. package/dist/utils/agents/adapters/notification.js +0 -16
  41. package/dist/utils/agents/adapters/repository.js +0 -61
  42. package/dist/utils/agents/adapters/research.js +0 -25
  43. package/dist/utils/agents/adapters/verification.js +0 -62
  44. package/dist/utils/agents/cli-tools.js +0 -5
  45. package/dist/utils/agents/contracts/messages.d.ts +0 -1
  46. package/dist/utils/agents/contracts/messages.js +0 -1
  47. package/dist/utils/agents/contracts/run.d.ts +0 -1
  48. package/dist/utils/agents/contracts/run.js +0 -1
  49. package/dist/utils/agents/runtime-types.d.ts +0 -1
  50. package/dist/utils/agents/runtime-types.js +0 -1
  51. package/dist/utils/books-data.js +0 -14
  52. package/dist/utils/plugin-runtime.js +0 -158
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @treeseed/core
2
2
 
3
- `@treeseed/core` is the Treeseed runtime package for Astro/Starlight sites. It contains the published runtime, shared components and styles, forms and deploy helpers, plugin runtime wiring, and agent-facing utilities used by Treeseed tenants.
3
+ `@treeseed/core` is the Treeseed Research Hub package for Astro/Starlight sites. It contains the published site runtime, shared components and styles, the knowledge-factory content model, and the Astro-specific forms stack used by Treeseed tenants.
4
4
 
5
5
  This repository is the package root. Run package commands from [`core`](./), not from the top-level `treeseed` workspace.
6
6
 
@@ -35,7 +35,19 @@ npm ci
35
35
  - `.github/workflows/`: CI and publish workflows for this package repo
36
36
  - `templates/github/deploy.workflow.yml`: downstream tenant deploy workflow template
37
37
 
38
- The package builds directly against the canonical working-site fixture in `treeseed-fixtures`.
38
+ The package builds directly against the canonical shared working-site fixture in `treeseed-fixtures`.
39
+
40
+ ## Shared Fixture Usage
41
+
42
+ `@treeseed/core` validates itself against the integrated shared fixture, not a Core-specific fork.
43
+
44
+ That means:
45
+
46
+ - the fixture may reference package surfaces owned by `sdk` and `agent`
47
+ - Core does not gain a real dependency on `@treeseed/agent`
48
+ - isolated Core verification may provide an Agent contracts shim so the shared fixture can typecheck and build without the full Agent runtime package
49
+
50
+ This keeps the shared fixture canonical while preserving Core’s package boundary.
39
51
 
40
52
  ## Commands
41
53
 
@@ -123,6 +135,8 @@ The package currently depends on:
123
135
  - Tailwind/Vite integration used by the site runtime
124
136
  - Wrangler for Cloudflare-oriented runtime and deploy support
125
137
 
138
+ It does not depend on `@treeseed/agent`.
139
+
126
140
  ## Contributor Workflow
127
141
 
128
142
  Typical local workflow:
package/dist/config.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import starlight from './vendor/starlight/index.js';
2
+ import { loadTreeseedManifest } from '@treeseed/sdk/platform/tenant-config';
2
3
  import { createTreeseedSite } from './site.js';
3
- import { loadTreeseedManifest } from './tenant/config.js';
4
4
 
5
5
  export function createTreeseedTenantSite(manifestPath) {
6
6
  const tenant = loadTreeseedManifest(manifestPath);
@@ -1,7 +1,7 @@
1
+ import { loadTreeseedManifest } from '@treeseed/sdk/platform/tenant-config';
1
2
  import { docsLoader } from './vendor/starlight/loaders.js';
2
3
  import { docsSchema } from './vendor/starlight/schema.js';
3
4
  import { createTreeseedCollections } from './content.js';
4
- import { loadTreeseedManifest } from './tenant/config.js';
5
5
 
6
6
  export function createTreeseedTenantCollections(manifestPath) {
7
7
  const tenant = loadTreeseedManifest(manifestPath);
package/dist/content.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { defineCollection, reference } from "astro:content";
2
2
  import { z } from "astro/zod";
3
3
  import { glob } from "astro/loaders";
4
- import { AGENT_CLI_ALLOW_TOOLS } from "./types/agents.js";
5
- import { loadTreeseedPluginRuntime } from "./plugins/runtime.js";
6
- import { loadTreeseedDeployConfig } from "./deploy/config.js";
4
+ import { AGENT_CLI_ALLOW_TOOLS } from "@treeseed/sdk/types/agents";
5
+ import { loadTreeseedPluginRuntime } from "@treeseed/sdk/platform/plugins";
6
+ import { loadTreeseedDeployConfig } from "@treeseed/sdk/platform/deploy-config";
7
7
  import {
8
8
  AGENT_MODEL_DEFAULTS,
9
9
  BOOK_MODEL_DEFAULTS,
package/dist/index.js CHANGED
@@ -1,38 +1,3 @@
1
- import {
2
- defineTreeseedTenant,
3
- getTenantContentRoot,
4
- loadTreeseedManifest,
5
- loadTreeseedTenantManifest,
6
- tenantFeatureEnabled
7
- } from "./tenant/config.js";
8
- import { deriveCloudflareWorkerName, loadTreeseedDeployConfig, resolveTreeseedDeployConfigPath } from "./deploy/config.js";
9
- import {
10
- getTreeseedAgentProviderSelections,
11
- getTreeseedDeployConfig,
12
- getTreeseedDeployProvider,
13
- getTreeseedDocsProvider,
14
- getTreeseedFormsProvider,
15
- getTreeseedOperationsProvider,
16
- getTreeseedSiteProvider,
17
- isTreeseedSmtpEnabled,
18
- isTreeseedTurnstileEnabled,
19
- resetTreeseedDeployConfigForTests
20
- } from "./deploy/runtime.js";
21
- import { defineTreeseedPlugin } from "./plugins/plugin.js";
22
- import { loadTreeseedPluginRuntime, loadTreeseedPlugins } from "./plugins/runtime.js";
23
- import {
24
- getTreeseedEnvironmentSuggestedValues,
25
- isTreeseedEnvironmentEntryRelevant,
26
- loadTreeseedEnvironmentOverlay,
27
- resolveTreeseedEnvironmentContext,
28
- resolveTreeseedEnvironmentRegistry,
29
- TREESEED_ENVIRONMENT_PURPOSES,
30
- TREESEED_ENVIRONMENT_REQUIREMENTS,
31
- TREESEED_ENVIRONMENT_SCOPES,
32
- TREESEED_ENVIRONMENT_SENSITIVITY,
33
- TREESEED_ENVIRONMENT_TARGETS,
34
- validateTreeseedEnvironmentValues
35
- } from "./environment.js";
36
1
  import {
37
2
  buildTreeseedSiteLayers,
38
3
  resolveTreeseedPageEntrypoint,
@@ -42,42 +7,10 @@ import {
42
7
  } from "./site-resources.js";
43
8
  import { parseSiteConfig } from "./utils/site-config-schema.js";
44
9
  export {
45
- TREESEED_ENVIRONMENT_PURPOSES,
46
- TREESEED_ENVIRONMENT_REQUIREMENTS,
47
- TREESEED_ENVIRONMENT_SCOPES,
48
- TREESEED_ENVIRONMENT_SENSITIVITY,
49
- TREESEED_ENVIRONMENT_TARGETS,
50
10
  TREESEED_SITE_RESOURCE_KINDS,
51
11
  buildTreeseedSiteLayers,
52
- defineTreeseedPlugin,
53
- defineTreeseedTenant,
54
- deriveCloudflareWorkerName,
55
- getTenantContentRoot,
56
- getTreeseedAgentProviderSelections,
57
- getTreeseedDeployConfig,
58
- getTreeseedDeployProvider,
59
- getTreeseedDocsProvider,
60
- getTreeseedEnvironmentSuggestedValues,
61
- getTreeseedFormsProvider,
62
- getTreeseedOperationsProvider,
63
- getTreeseedSiteProvider,
64
- isTreeseedEnvironmentEntryRelevant,
65
- isTreeseedSmtpEnabled,
66
- isTreeseedTurnstileEnabled,
67
- loadTreeseedDeployConfig,
68
- loadTreeseedEnvironmentOverlay,
69
- loadTreeseedManifest,
70
- loadTreeseedPluginRuntime,
71
- loadTreeseedPlugins,
72
- loadTreeseedTenantManifest,
73
12
  parseSiteConfig,
74
- resetTreeseedDeployConfigForTests,
75
- resolveTreeseedDeployConfigPath,
76
- resolveTreeseedEnvironmentContext,
77
- resolveTreeseedEnvironmentRegistry,
78
13
  resolveTreeseedPageEntrypoint,
79
14
  resolveTreeseedSiteResource,
80
- resolveTreeseedStyleEntrypoint,
81
- tenantFeatureEnabled,
82
- validateTreeseedEnvironmentValues
15
+ resolveTreeseedStyleEntrypoint
83
16
  };
@@ -1,6 +1,6 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
- import { BOOKS, TREESEED_LIBRARY_DOWNLOAD } from '../utils/books-data.js';
3
+ import { BOOKS, TREESEED_LIBRARY_DOWNLOAD } from '@treeseed/sdk/platform/books-data';
4
4
  import { PROJECT_TENANT } from '../tenant/bridge.js';
5
5
  const projectRoot = PROJECT_TENANT.__tenantRoot ?? process.cwd();
6
6
  const outputDir = path.join(projectRoot, 'public', 'books');
@@ -128,11 +128,7 @@ function rewriteScriptRuntimeSpecifiers(contents) {
128
128
  .replace(/(['"`])\.\.\/src\//g, '$1../')
129
129
  .replace(/(['"`])\.\/src\//g, '$1./dist/')
130
130
  .replaceAll("'dist/worker/forms-worker.js'", "'dist/worker/forms-worker.js'")
131
- .replaceAll('"dist/worker/forms-worker.js"', '"dist/worker/forms-worker.js"')
132
- .replaceAll("'../deploy/config.js'", "'../deploy/config.js'")
133
- .replaceAll('"../deploy/config.js"', '"../deploy/config.js"')
134
- .replaceAll("'../deploy/config.js'", "'../deploy/config.js'")
135
- .replaceAll('"../deploy/config.js"', '"../deploy/config.js"');
131
+ .replaceAll('"dist/worker/forms-worker.js"', '"dist/worker/forms-worker.js"');
136
132
  }
137
133
  async function compileModule(filePath, sourceRoot, outputRoot) {
138
134
  const relativePath = relative(sourceRoot, filePath);
@@ -208,15 +204,8 @@ function rewriteDeclarations() {
208
204
  }
209
205
  function emitTypeDeclarations() {
210
206
  const sourceFiles = [
211
- resolve(srcRoot, 'contracts.ts'),
212
- resolve(srcRoot, 'environment.ts'),
213
- resolve(srcRoot, 'types/agents.ts'),
214
207
  resolve(srcRoot, 'types/cloudflare.ts'),
215
- resolve(srcRoot, 'plugins/plugin.ts'),
216
208
  resolve(srcRoot, 'site-resources.ts'),
217
- resolve(srcRoot, 'utils/agents/runtime-types.ts'),
218
- resolve(srcRoot, 'utils/agents/contracts/messages.ts'),
219
- resolve(srcRoot, 'utils/agents/contracts/run.ts'),
220
209
  ].filter((filePath) => existsSync(filePath));
221
210
  if (sourceFiles.length === 0) {
222
211
  return;
@@ -367,9 +356,9 @@ async function main() {
367
356
  const contents = readFileSync(filePath, 'utf8');
368
357
  writeFileSync(filePath, rewriteTreeseedStarlightSpecifiers(contents, filePath), 'utf8');
369
358
  }
370
- writeCompatibilityEntrypoint(resolve(distRoot, 'config.js'), "import starlight from './vendor/starlight/index.js';\nimport { createTreeseedSite } from './site.js';\nimport { loadTreeseedManifest } from './tenant/config.js';\n\nexport function createTreeseedTenantSite(manifestPath) {\n\tconst tenant = loadTreeseedManifest(manifestPath);\n\treturn createTreeseedSite(tenant, { starlight });\n}");
359
+ writeCompatibilityEntrypoint(resolve(distRoot, 'config.js'), "import starlight from './vendor/starlight/index.js';\nimport { loadTreeseedManifest } from '@treeseed/sdk/platform/tenant-config';\nimport { createTreeseedSite } from './site.js';\n\nexport function createTreeseedTenantSite(manifestPath) {\n\tconst tenant = loadTreeseedManifest(manifestPath);\n\treturn createTreeseedSite(tenant, { starlight });\n}");
371
360
  writeCompatibilityEntrypoint(resolve(distRoot, 'config.d.ts'), "export declare function createTreeseedTenantSite(manifestPath?: string): import('astro').AstroUserConfig<never, never, never>;");
372
- writeCompatibilityEntrypoint(resolve(distRoot, 'content-config.js'), "import { docsLoader } from './vendor/starlight/loaders.js';\nimport { docsSchema } from './vendor/starlight/schema.js';\nimport { createTreeseedCollections } from './content.js';\nimport { loadTreeseedManifest } from './tenant/config.js';\n\nexport function createTreeseedTenantCollections(manifestPath) {\n\tconst tenant = loadTreeseedManifest(manifestPath);\n\treturn createTreeseedCollections(tenant, { docsLoader, docsSchema });\n}");
361
+ writeCompatibilityEntrypoint(resolve(distRoot, 'content-config.js'), "import { loadTreeseedManifest } from '@treeseed/sdk/platform/tenant-config';\nimport { docsLoader } from './vendor/starlight/loaders.js';\nimport { docsSchema } from './vendor/starlight/schema.js';\nimport { createTreeseedCollections } from './content.js';\n\nexport function createTreeseedTenantCollections(manifestPath) {\n\tconst tenant = loadTreeseedManifest(manifestPath);\n\treturn createTreeseedCollections(tenant, { docsLoader, docsSchema });\n}");
373
362
  writeCompatibilityEntrypoint(resolve(distRoot, 'content-config.d.ts'), "export declare function createTreeseedTenantCollections(manifestPath?: string): {\n\tpages: any;\n\tnotes: any;\n\tquestions: any;\n\tobjectives: any;\n\tpeople: any;\n\tagents: any;\n\tbooks: any;\n\tdocs: any;\n};");
374
363
  rmSync(resolve(distRoot, 'config.d.js'), { force: true });
375
364
  rmSync(resolve(distRoot, 'content-config.d.js'), { force: true });
@@ -1,8 +1,8 @@
1
1
  import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
2
  import { dirname, resolve } from 'node:path';
3
3
  import { build } from 'esbuild';
4
- import { loadTreeseedDeployConfig } from '../deploy/config.js';
5
- import { loadTreeseedManifest } from '../tenant/config.js';
4
+ import { loadTreeseedDeployConfig } from '@treeseed/sdk/platform/deploy-config';
5
+ import { loadTreeseedManifest } from '@treeseed/sdk/platform/tenant-config';
6
6
  import { parseSiteConfig } from '../utils/site-config-schema.js';
7
7
  import { packageRoot } from './package-tools.js';
8
8
  const tenantRoot = process.cwd();
@@ -1,26 +1,229 @@
1
- import { mkdirSync, writeFileSync } from 'node:fs';
1
+ import { existsSync, mkdirSync, rmSync, symlinkSync, writeFileSync } from 'node:fs';
2
2
  import { spawnSync } from 'node:child_process';
3
- import { join, resolve } from 'node:path';
3
+ import { dirname, resolve } from 'node:path';
4
+ import { createRequire } from 'node:module';
4
5
  import { fixtureRoot, packageRoot } from './paths.js';
5
6
  const [command, ...rest] = process.argv.slice(2);
7
+ const require = createRequire(import.meta.url);
6
8
  if (!command) {
7
9
  console.error('Usage: node ./scripts/run-fixture-astro-command.mjs <check|build|preview|dev> [...args]');
8
10
  process.exit(1);
9
11
  }
10
- function ensureFixtureDefaultPluginPackage() {
11
- const packageDir = resolve(fixtureRoot, 'node_modules', '@treeseed', 'core');
12
- const pluginEntryPath = resolve(packageRoot, 'dist', 'plugin-default.js');
13
- mkdirSync(packageDir, { recursive: true });
14
- writeFileSync(join(packageDir, 'package.json'), `${JSON.stringify({
15
- name: '@treeseed/core',
16
- type: 'commonjs',
12
+ function resolveInstalledPackageRoot(packageName) {
13
+ const packageJsonCandidate = (() => {
14
+ try {
15
+ return require.resolve(`${packageName}/package.json`);
16
+ }
17
+ catch {
18
+ return null;
19
+ }
20
+ })();
21
+ if (packageJsonCandidate) {
22
+ return dirname(packageJsonCandidate);
23
+ }
24
+ const moduleEntryCandidate = (() => {
25
+ try {
26
+ return require.resolve(packageName);
27
+ }
28
+ catch {
29
+ return null;
30
+ }
31
+ })();
32
+ if (!moduleEntryCandidate) {
33
+ return null;
34
+ }
35
+ let currentDir = dirname(moduleEntryCandidate);
36
+ while (currentDir !== dirname(currentDir)) {
37
+ if (existsSync(resolve(currentDir, 'package.json'))) {
38
+ return currentDir;
39
+ }
40
+ currentDir = dirname(currentDir);
41
+ }
42
+ return null;
43
+ }
44
+ function ensureFixtureWorkspacePackage(packageName, workspaceDir) {
45
+ const packageDir = resolve(fixtureRoot, 'node_modules', ...packageName.split('/'));
46
+ const resolvedPackageRoot = [
47
+ workspaceDir,
48
+ resolveInstalledPackageRoot(packageName),
49
+ ].find((candidate) => Boolean(candidate) && existsSync(candidate));
50
+ if (!resolvedPackageRoot) {
51
+ throw new Error(`Unable to resolve the ${packageName} package root for the fixture runtime.`);
52
+ }
53
+ mkdirSync(dirname(packageDir), { recursive: true });
54
+ rmSync(packageDir, { recursive: true, force: true });
55
+ symlinkSync(resolvedPackageRoot, packageDir, 'dir');
56
+ }
57
+ function ensureFixtureAgentContractPackage() {
58
+ const packageDir = resolve(fixtureRoot, 'node_modules', '@treeseed', 'agent');
59
+ mkdirSync(resolve(packageDir, 'contracts'), { recursive: true });
60
+ writeFileSync(resolve(packageDir, 'package.json'), JSON.stringify({
61
+ name: '@treeseed/agent',
62
+ type: 'module',
17
63
  exports: {
18
- './plugin-default': './plugin-default.cjs',
64
+ './runtime-types': {
65
+ types: './runtime-types.d.js',
66
+ default: './runtime-types.js',
67
+ },
68
+ './contracts/messages': {
69
+ types: './contracts/messages.d.js',
70
+ default: './contracts/messages.js',
71
+ },
72
+ './contracts/run': {
73
+ types: './contracts/run.d.js',
74
+ default: './contracts/run.js',
75
+ },
19
76
  },
20
- }, null, 2)}\n`, 'utf8');
21
- writeFileSync(join(packageDir, 'plugin-default.cjs'), `module.exports = require(${JSON.stringify(pluginEntryPath)});\n`, 'utf8');
77
+ }, null, 2), 'utf8');
78
+ writeFileSync(resolve(packageDir, 'runtime-types.js'), 'export {};\n', 'utf8');
79
+ writeFileSync(resolve(packageDir, 'runtime-types.d.ts'), [
80
+ "import type { AgentHandlerKind, AgentRunStatus } from '@treeseed/sdk/types/agents';",
81
+ 'export interface AgentTriggerInvocation {',
82
+ "\tkind: 'startup' | 'schedule' | 'message' | 'manual' | 'follow';",
83
+ '\tsource: string;',
84
+ '\tmessage?: { id?: string | number; type?: string; payloadJson?: string | null } | null;',
85
+ '}',
86
+ 'export interface AgentExecutionResult {',
87
+ '\tstatus: AgentRunStatus;',
88
+ '\tsummary: string;',
89
+ '\tstdout?: string;',
90
+ '\tstderr?: string;',
91
+ "\terrorCategory?: import('./contracts/run.js').AgentErrorCategory | null;",
92
+ '\tmetadata?: Record<string, unknown>;',
93
+ '}',
94
+ 'export interface AgentContext {',
95
+ '\trunId: string;',
96
+ '\trepoRoot: string;',
97
+ '\tagent: any;',
98
+ '\tsdk: any;',
99
+ '\ttrigger: AgentTriggerInvocation;',
100
+ '\texecution: any;',
101
+ '\tmutations: any;',
102
+ '\trepository: any;',
103
+ '\tverification: any;',
104
+ '\tnotifications: any;',
105
+ '\tresearch: any;',
106
+ '}',
107
+ 'export interface AgentHandler<TInputs = unknown, TResult = unknown> {',
108
+ '\tkind: AgentHandlerKind;',
109
+ '\tresolveInputs(context: AgentContext): Promise<TInputs>;',
110
+ '\texecute(context: AgentContext, inputs: TInputs): Promise<TResult>;',
111
+ '\temitOutputs(context: AgentContext, result: TResult): Promise<AgentExecutionResult>;',
112
+ '}',
113
+ '',
114
+ ].join('\n'), 'utf8');
115
+ writeFileSync(resolve(packageDir, 'contracts', 'messages.js'), [
116
+ 'export const AGENT_MESSAGE_TYPES = {};',
117
+ 'export function parseAgentMessagePayload(_type, payloadJson) {',
118
+ '\treturn JSON.parse(payloadJson);',
119
+ '}',
120
+ '',
121
+ ].join('\n'), 'utf8');
122
+ writeFileSync(resolve(packageDir, 'contracts', 'messages.d.ts'), [
123
+ 'export interface QuestionPriorityUpdatedMessage {',
124
+ '\tquestionId: string;',
125
+ '\treason: string;',
126
+ '\tplannerRunId: string;',
127
+ '}',
128
+ 'export interface ObjectivePriorityUpdatedMessage {',
129
+ '\tobjectiveId: string;',
130
+ '\treason: string;',
131
+ '\tplannerRunId: string;',
132
+ '}',
133
+ 'export interface ArchitectureUpdatedMessage {',
134
+ '\tobjectiveId: string;',
135
+ '\tknowledgeId: string;',
136
+ '\tarchitectRunId: string;',
137
+ '}',
138
+ 'export interface SubscriberNotifiedMessage {',
139
+ '\temail: string;',
140
+ '\titemCount: number;',
141
+ '\tnotifierRunId: string;',
142
+ '}',
143
+ 'export interface ResearchStartedMessage {',
144
+ '\tquestionId: string;',
145
+ '\tresearcherRunId: string;',
146
+ '}',
147
+ 'export interface ResearchCompletedMessage {',
148
+ '\tquestionId: string;',
149
+ '\tknowledgeId: string | null;',
150
+ '\tresearcherRunId: string;',
151
+ '}',
152
+ 'export interface TaskCompleteMessage {',
153
+ '\tbranchName: string | null;',
154
+ '\tchangedTargets: string[];',
155
+ '\tengineerRunId: string;',
156
+ '}',
157
+ 'export interface TaskWaitingMessage {',
158
+ '\tblockingReason: string;',
159
+ '\tengineerRunId: string;',
160
+ '}',
161
+ 'export interface TaskFailedMessage {',
162
+ '\tfailureSummary: string;',
163
+ '\tengineerRunId: string;',
164
+ '}',
165
+ 'export interface TaskVerifiedMessage {',
166
+ '\tbranchName: string | null;',
167
+ '\treviewerRunId: string;',
168
+ '}',
169
+ 'export interface ReviewFailedMessage {',
170
+ '\tfailureSummary: string;',
171
+ '\treviewerRunId: string;',
172
+ '}',
173
+ 'export interface ReviewWaitingMessage {',
174
+ '\tblockingReason: string;',
175
+ '\treviewerRunId: string;',
176
+ '}',
177
+ 'export interface ReleaseStartedMessage {',
178
+ '\ttaskRunId: string | null;',
179
+ '\treleaserRunId: string;',
180
+ '}',
181
+ 'export interface ReleaseCompletedMessage {',
182
+ '\treleaseSummary: string;',
183
+ '\treleaserRunId: string;',
184
+ '}',
185
+ 'export interface ReleaseFailedMessage {',
186
+ '\tfailureSummary: string;',
187
+ '\treleaserRunId: string;',
188
+ '}',
189
+ 'export interface AgentMessageContracts {',
190
+ '\tquestion_priority_updated: QuestionPriorityUpdatedMessage;',
191
+ '\tobjective_priority_updated: ObjectivePriorityUpdatedMessage;',
192
+ '\tarchitecture_updated: ArchitectureUpdatedMessage;',
193
+ '\tsubscriber_notified: SubscriberNotifiedMessage;',
194
+ '\tresearch_started: ResearchStartedMessage;',
195
+ '\tresearch_completed: ResearchCompletedMessage;',
196
+ '\ttask_complete: TaskCompleteMessage;',
197
+ '\ttask_waiting: TaskWaitingMessage;',
198
+ '\ttask_failed: TaskFailedMessage;',
199
+ '\ttask_verified: TaskVerifiedMessage;',
200
+ '\treview_failed: ReviewFailedMessage;',
201
+ '\treview_waiting: ReviewWaitingMessage;',
202
+ '\trelease_started: ReleaseStartedMessage;',
203
+ '\trelease_completed: ReleaseCompletedMessage;',
204
+ '\trelease_failed: ReleaseFailedMessage;',
205
+ '}',
206
+ 'export type AgentMessageType = keyof AgentMessageContracts;',
207
+ 'export type AgentMessagePayload<TType extends AgentMessageType> = AgentMessageContracts[TType];',
208
+ 'export declare const AGENT_MESSAGE_TYPES: readonly AgentMessageType[];',
209
+ 'export declare function parseAgentMessagePayload<TType extends AgentMessageType>(_type: TType, payloadJson: string): AgentMessagePayload<TType>;',
210
+ '',
211
+ ].join('\n'), 'utf8');
212
+ writeFileSync(resolve(packageDir, 'contracts', 'run.js'), 'export {};\n', 'utf8');
213
+ writeFileSync(resolve(packageDir, 'contracts', 'run.d.ts'), [
214
+ "export type AgentErrorCategory = 'execution_error' | 'mutation_error' | 'verification_error' | 'notification_error' | 'research_error' | 'sdk_error' | 'unknown';",
215
+ '',
216
+ ].join('\n'), 'utf8');
217
+ }
218
+ ensureFixtureWorkspacePackage('@treeseed/sdk', resolve(packageRoot, '..', 'sdk'));
219
+ const workspaceAgentRoot = resolve(packageRoot, '..', 'agent');
220
+ if (existsSync(workspaceAgentRoot) || resolveInstalledPackageRoot('@treeseed/agent')) {
221
+ ensureFixtureWorkspacePackage('@treeseed/agent', workspaceAgentRoot);
222
+ }
223
+ else {
224
+ rmSync(resolve(fixtureRoot, 'node_modules', '@treeseed', 'agent'), { recursive: true, force: true });
225
+ ensureFixtureAgentContractPackage();
22
226
  }
23
- ensureFixtureDefaultPluginPackage();
24
227
  const result = spawnSync('npx', ['astro', command, '--root', fixtureRoot, ...rest], {
25
228
  cwd: packageRoot,
26
229
  stdio: 'inherit',
@@ -1,5 +1,5 @@
1
- import type { TreeseedDeployConfig, TreeseedTenantConfig } from './contracts';
2
- import type { LoadedTreeseedPluginEntry } from './plugins/runtime';
1
+ import type { TreeseedDeployConfig, TreeseedTenantConfig } from '@treeseed/sdk/platform/contracts';
2
+ import type { LoadedTreeseedPluginEntry } from '@treeseed/sdk/platform/plugins';
3
3
  export declare const TREESEED_SITE_RESOURCE_KINDS: readonly ["pages", "styles", "components"];
4
4
  export type TreeseedSiteResourceKind = (typeof TREESEED_SITE_RESOURCE_KINDS)[number];
5
5
  export type TreeseedSiteLayerDefinition = {
package/dist/site.js CHANGED
@@ -6,11 +6,11 @@ import rehypeKatex from "rehype-katex";
6
6
  import remarkMath from "remark-math";
7
7
  import tailwindcss from "@tailwindcss/vite";
8
8
  import { parseSiteConfig } from "./utils/site-config-schema.js";
9
- import { buildTenantBookRuntime } from "./utils/books-data.js";
9
+ import { buildTenantBookRuntime } from "@treeseed/sdk/platform/books-data";
10
10
  import { getStarlightSidebarConfigFromRuntime } from "./utils/starlight-nav.js";
11
11
  import { buildTenantThemeCss } from "./utils/theme.js";
12
- import { loadTreeseedDeployConfig } from "./deploy/config.js";
13
- import { loadTreeseedPluginRuntime } from "./plugins/runtime.js";
12
+ import { loadTreeseedDeployConfig } from "@treeseed/sdk/platform/deploy-config";
13
+ import { loadTreeseedPluginRuntime } from "@treeseed/sdk/platform/plugins";
14
14
  import {
15
15
  buildTreeseedSiteLayers,
16
16
  resolveTreeseedPageEntrypoint,
@@ -1,4 +1,4 @@
1
- import { loadTreeseedManifest } from "./config.js";
1
+ import { loadTreeseedManifest } from "@treeseed/sdk/platform/tenant-config";
2
2
  const PROJECT_TENANT = loadTreeseedManifest();
3
3
  export {
4
4
  PROJECT_TENANT
@@ -1,5 +1,5 @@
1
1
  import { readFileSync } from "node:fs";
2
- import { loadTreeseedManifest } from "./config.js";
2
+ import { loadTreeseedManifest } from "@treeseed/sdk/platform/tenant-config";
3
3
  import { parseSiteConfig } from "../utils/site-config-schema.js";
4
4
  const injectedTenantConfig = typeof __TREESEED_TENANT_CONFIG__ !== "undefined" ? __TREESEED_TENANT_CONFIG__ : null;
5
5
  const injectedProjectRoot = typeof __TREESEED_PROJECT_ROOT__ !== "undefined" ? __TREESEED_PROJECT_ROOT__ : null;
@@ -15,7 +15,11 @@ import {
15
15
  TREESEED_TURNSTILE_SECRET_KEY
16
16
  } from "astro:env/server";
17
17
  import { SITE_EMAIL_NOTIFICATIONS } from "../site-config.js";
18
- import { getTreeseedFormsProvider, isTreeseedSmtpEnabled, isTreeseedTurnstileEnabled } from "../../deploy/runtime.js";
18
+ import {
19
+ getTreeseedFormsProvider,
20
+ isTreeseedSmtpEnabled,
21
+ isTreeseedTurnstileEnabled
22
+ } from "@treeseed/sdk/platform/deploy-runtime";
19
23
  function getFormSecret() {
20
24
  return TREESEED_FORM_TOKEN_SECRET ?? "";
21
25
  }
@@ -0,0 +1,42 @@
1
+ import { getTreeseedFormsProvider } from "@treeseed/sdk/platform/deploy-runtime";
2
+ import { loadTreeseedPluginRuntime } from "@treeseed/sdk/platform/plugins";
3
+ import { BUILTIN_FORMS_PROVIDERS, finalizeFormsProvider } from "./provider-core.js";
4
+ let cachedFormsRuntime = null;
5
+ function readPluginRecord(pluginEntry, key) {
6
+ const value = pluginEntry.plugin[key];
7
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
8
+ }
9
+ function assertUniqueProvider(registry, id, owner) {
10
+ if (registry.has(id)) {
11
+ throw new Error(`Treeseed plugin runtime found duplicate provider "${id}" from ${owner}.`);
12
+ }
13
+ }
14
+ function resetTreeseedFormsProviderRuntimeForTests() {
15
+ cachedFormsRuntime = null;
16
+ }
17
+ function resolveFormsProvider(providerId = getTreeseedFormsProvider()) {
18
+ if (!cachedFormsRuntime) {
19
+ const runtime = loadTreeseedPluginRuntime();
20
+ const providers = /* @__PURE__ */ new Map();
21
+ for (const provider2 of Object.values(BUILTIN_FORMS_PROVIDERS)) {
22
+ providers.set(provider2.id, provider2);
23
+ }
24
+ for (const pluginEntry of runtime.plugins) {
25
+ const contributedProviders = readPluginRecord(pluginEntry, "formsProviders");
26
+ for (const [id, provider2] of Object.entries(contributedProviders)) {
27
+ assertUniqueProvider(providers, id, pluginEntry.package);
28
+ providers.set(id, provider2);
29
+ }
30
+ }
31
+ cachedFormsRuntime = { providers };
32
+ }
33
+ const provider = cachedFormsRuntime.providers.get(providerId);
34
+ if (!provider) {
35
+ throw new Error(`Treeseed forms provider "${providerId}" is not registered.`);
36
+ }
37
+ return finalizeFormsProvider(provider);
38
+ }
39
+ export {
40
+ resetTreeseedFormsProviderRuntimeForTests,
41
+ resolveFormsProvider
42
+ };
@@ -1,5 +1,5 @@
1
- import { getTreeseedFormsProvider } from "../../deploy/runtime.js";
2
- import { resolveFormsProvider } from "../plugin-runtime.js";
1
+ import { getTreeseedFormsProvider } from "@treeseed/sdk/platform/deploy-runtime";
2
+ import { resolveFormsProvider } from "./provider-runtime.js";
3
3
  import {
4
4
  getContactRoutingMap,
5
5
  getFormSecret,
@@ -1,4 +1,9 @@
1
- import { BOOKS, BOOKS_LINK, TREESEED_LIBRARY_DOWNLOAD, TREESEED_LINKS } from "./books-data.js";
1
+ import {
2
+ BOOKS,
3
+ BOOKS_LINK,
4
+ TREESEED_LIBRARY_DOWNLOAD,
5
+ TREESEED_LINKS
6
+ } from "@treeseed/sdk/platform/books-data";
2
7
  const normalizeHref = (href) => href.endsWith("/") ? href : `${href}/`;
3
8
  function buildBookSidebarFromRuntime(runtime2, bookSlug) {
4
9
  const book = runtime2.BOOKS.find((candidate) => candidate.slug === bookSlug);