@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
package/dist/plugins/runtime.js
CHANGED
|
@@ -1,120 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import builtinDefaultPlugin from "./builtin/default-plugin.js";
|
|
7
|
-
const require2 = createRequire(import.meta.url);
|
|
8
|
-
function normalizeLoadedPlugin(moduleExports, packageName) {
|
|
9
|
-
const plugin = moduleExports?.default ?? moduleExports;
|
|
10
|
-
if (!plugin || typeof plugin !== "object") {
|
|
11
|
-
throw new Error(`Treeseed plugin "${packageName}" did not export a plugin object.`);
|
|
12
|
-
}
|
|
13
|
-
return plugin;
|
|
14
|
-
}
|
|
15
|
-
function isPathLikePluginReference(packageName) {
|
|
16
|
-
return packageName.startsWith(".") || packageName.startsWith("/") || packageName.startsWith("file:");
|
|
17
|
-
}
|
|
18
|
-
function loadPluginModule(packageName, tenantRoot) {
|
|
19
|
-
if (packageName === TREESEED_DEFAULT_PLUGIN_PACKAGE) {
|
|
20
|
-
return {
|
|
21
|
-
moduleExports: builtinDefaultPlugin,
|
|
22
|
-
baseDir: fileURLToPath(new URL("..", import.meta.url))
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
if (isPathLikePluginReference(packageName)) {
|
|
26
|
-
const resolvedPath2 = packageName.startsWith("file:") ? fileURLToPath(packageName) : path.resolve(tenantRoot, packageName);
|
|
27
|
-
return {
|
|
28
|
-
moduleExports: require2(resolvedPath2),
|
|
29
|
-
baseDir: path.dirname(resolvedPath2)
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
const resolvedPath = require2.resolve(packageName);
|
|
33
|
-
return {
|
|
34
|
-
moduleExports: require2(resolvedPath),
|
|
35
|
-
baseDir: path.dirname(resolvedPath)
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
function loadTreeseedPlugins(config = loadTreeseedDeployConfig()) {
|
|
39
|
-
const tenantRoot = config.__tenantRoot ?? process.cwd();
|
|
40
|
-
const plugins = [];
|
|
41
|
-
for (const pluginRef of config.plugins ?? []) {
|
|
42
|
-
if (pluginRef?.enabled === false) {
|
|
43
|
-
continue;
|
|
44
|
-
}
|
|
45
|
-
const loaded = loadPluginModule(pluginRef.package, tenantRoot);
|
|
46
|
-
const plugin = normalizeLoadedPlugin(loaded.moduleExports, pluginRef.package);
|
|
47
|
-
plugins.push({
|
|
48
|
-
package: pluginRef.package,
|
|
49
|
-
config: pluginRef.config ?? {},
|
|
50
|
-
baseDir: loaded.baseDir,
|
|
51
|
-
plugin
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
return plugins;
|
|
55
|
-
}
|
|
56
|
-
function collectProvidedIds(plugins) {
|
|
57
|
-
const provided = {
|
|
58
|
-
forms: /* @__PURE__ */ new Set(),
|
|
59
|
-
agents: {
|
|
60
|
-
execution: /* @__PURE__ */ new Set(),
|
|
61
|
-
mutation: /* @__PURE__ */ new Set(),
|
|
62
|
-
repository: /* @__PURE__ */ new Set(),
|
|
63
|
-
verification: /* @__PURE__ */ new Set(),
|
|
64
|
-
notification: /* @__PURE__ */ new Set(),
|
|
65
|
-
research: /* @__PURE__ */ new Set(),
|
|
66
|
-
handlers: /* @__PURE__ */ new Set()
|
|
67
|
-
},
|
|
68
|
-
deploy: /* @__PURE__ */ new Set(),
|
|
69
|
-
content: {
|
|
70
|
-
docs: /* @__PURE__ */ new Set()
|
|
71
|
-
},
|
|
72
|
-
site: /* @__PURE__ */ new Set()
|
|
73
|
-
};
|
|
74
|
-
for (const { plugin } of plugins) {
|
|
75
|
-
for (const id of plugin.provides?.forms ?? []) provided.forms.add(id);
|
|
76
|
-
for (const id of plugin.provides?.agents?.execution ?? []) provided.agents.execution.add(id);
|
|
77
|
-
for (const id of plugin.provides?.agents?.mutation ?? []) provided.agents.mutation.add(id);
|
|
78
|
-
for (const id of plugin.provides?.agents?.repository ?? []) provided.agents.repository.add(id);
|
|
79
|
-
for (const id of plugin.provides?.agents?.verification ?? []) provided.agents.verification.add(id);
|
|
80
|
-
for (const id of plugin.provides?.agents?.notification ?? []) provided.agents.notification.add(id);
|
|
81
|
-
for (const id of plugin.provides?.agents?.research ?? []) provided.agents.research.add(id);
|
|
82
|
-
for (const id of plugin.provides?.agents?.handlers ?? []) provided.agents.handlers.add(id);
|
|
83
|
-
for (const id of plugin.provides?.deploy ?? []) provided.deploy.add(id);
|
|
84
|
-
for (const id of plugin.provides?.content?.docs ?? []) provided.content.docs.add(id);
|
|
85
|
-
for (const id of plugin.provides?.site ?? []) provided.site.add(id);
|
|
86
|
-
}
|
|
87
|
-
return provided;
|
|
88
|
-
}
|
|
89
|
-
function assertSelectedProvider(provided, label, id) {
|
|
90
|
-
if (!id) {
|
|
91
|
-
throw new Error(`Treeseed plugin runtime is missing selected provider id for ${label}.`);
|
|
92
|
-
}
|
|
93
|
-
if (!provided.has(id)) {
|
|
94
|
-
throw new Error(`Treeseed plugin runtime could not resolve ${label} provider "${id}".`);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
function loadTreeseedPluginRuntime(config = loadTreeseedDeployConfig()) {
|
|
98
|
-
const plugins = loadTreeseedPlugins(config);
|
|
99
|
-
const provided = collectProvidedIds(plugins);
|
|
100
|
-
const providers = config.providers;
|
|
101
|
-
assertSelectedProvider(provided.forms, "forms", providers.forms);
|
|
102
|
-
assertSelectedProvider(provided.agents.execution, "agents.execution", providers.agents.execution);
|
|
103
|
-
assertSelectedProvider(provided.agents.mutation, "agents.mutation", providers.agents.mutation);
|
|
104
|
-
assertSelectedProvider(provided.agents.repository, "agents.repository", providers.agents.repository);
|
|
105
|
-
assertSelectedProvider(provided.agents.verification, "agents.verification", providers.agents.verification);
|
|
106
|
-
assertSelectedProvider(provided.agents.notification, "agents.notification", providers.agents.notification);
|
|
107
|
-
assertSelectedProvider(provided.agents.research, "agents.research", providers.agents.research);
|
|
108
|
-
assertSelectedProvider(provided.deploy, "deploy", providers.deploy);
|
|
109
|
-
assertSelectedProvider(provided.content.docs, "content.docs", providers.content?.docs);
|
|
110
|
-
assertSelectedProvider(provided.site, "site", providers.site);
|
|
111
|
-
return {
|
|
112
|
-
config,
|
|
113
|
-
plugins,
|
|
114
|
-
provided
|
|
115
|
-
};
|
|
116
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
loadTreeseedPluginRuntime,
|
|
3
|
+
loadTreeseedPlugins,
|
|
4
|
+
resolveTreeseedGraphRankingProvider
|
|
5
|
+
} from "@treeseed/sdk/platform/plugins";
|
|
117
6
|
export {
|
|
118
7
|
loadTreeseedPluginRuntime,
|
|
119
|
-
loadTreeseedPlugins
|
|
8
|
+
loadTreeseedPlugins,
|
|
9
|
+
resolveTreeseedGraphRankingProvider
|
|
120
10
|
};
|
|
@@ -343,7 +343,7 @@ async function main() {
|
|
|
343
343
|
await compileModule(filePath, srcRoot, distRoot);
|
|
344
344
|
continue;
|
|
345
345
|
}
|
|
346
|
-
if (COPY_EXTENSIONS.has(extension)
|
|
346
|
+
if (COPY_EXTENSIONS.has(extension)) {
|
|
347
347
|
copyAsset(filePath, srcRoot, distRoot);
|
|
348
348
|
}
|
|
349
349
|
}
|
|
@@ -368,7 +368,11 @@ async function main() {
|
|
|
368
368
|
writeFileSync(filePath, rewriteTreeseedStarlightSpecifiers(contents, filePath), 'utf8');
|
|
369
369
|
}
|
|
370
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}");
|
|
371
|
+
writeCompatibilityEntrypoint(resolve(distRoot, 'config.d.ts'), "export declare function createTreeseedTenantSite(manifestPath?: string): import('astro').AstroUserConfig<never, never, never>;");
|
|
371
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}");
|
|
373
|
+
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
|
+
rmSync(resolve(distRoot, 'config.d.js'), { force: true });
|
|
375
|
+
rmSync(resolve(distRoot, 'content-config.d.js'), { force: true });
|
|
372
376
|
writeCompatibilityEntrypoint(resolve(vendoredStarlightRoot, 'utils', 'routing.js'), "export * from './routing/index.js';");
|
|
373
377
|
copyAsset(resolve(packageRoot, 'tsconfigs/strict.json'), packageRoot, distRoot);
|
|
374
378
|
copyPackageAsset('@astrojs/mdx', 'template/content-module-types.d.ts', 'template/content-module-types.d.ts');
|
|
@@ -43,8 +43,7 @@ function scanDirectory(root) {
|
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
|
-
run('npm', ['run', '
|
|
47
|
-
run('npm', ['run', 'build:dist']);
|
|
46
|
+
run('npm', ['run', 'lint']);
|
|
48
47
|
scanDirectory(resolve(packageRoot, 'dist'));
|
|
49
48
|
run('npm', ['run', 'test:unit']);
|
|
50
49
|
run('npm', ['run', 'check']);
|
|
@@ -1,10 +1,26 @@
|
|
|
1
|
+
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
1
2
|
import { spawnSync } from 'node:child_process';
|
|
3
|
+
import { join, resolve } from 'node:path';
|
|
2
4
|
import { fixtureRoot, packageRoot } from './paths.js';
|
|
3
5
|
const [command, ...rest] = process.argv.slice(2);
|
|
4
6
|
if (!command) {
|
|
5
7
|
console.error('Usage: node ./scripts/run-fixture-astro-command.mjs <check|build|preview|dev> [...args]');
|
|
6
8
|
process.exit(1);
|
|
7
9
|
}
|
|
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',
|
|
17
|
+
exports: {
|
|
18
|
+
'./plugin-default': './plugin-default.cjs',
|
|
19
|
+
},
|
|
20
|
+
}, null, 2)}\n`, 'utf8');
|
|
21
|
+
writeFileSync(join(packageDir, 'plugin-default.cjs'), `module.exports = require(${JSON.stringify(pluginEntryPath)});\n`, 'utf8');
|
|
22
|
+
}
|
|
23
|
+
ensureFixtureDefaultPluginPackage();
|
|
8
24
|
const result = spawnSync('npx', ['astro', command, '--root', fixtureRoot, ...rest], {
|
|
9
25
|
cwd: packageRoot,
|
|
10
26
|
stdio: 'inherit',
|
|
@@ -7,12 +7,17 @@ import { createRequire } from 'node:module';
|
|
|
7
7
|
import { packageRoot } from './package-tools.js';
|
|
8
8
|
const require = createRequire(import.meta.url);
|
|
9
9
|
const sdkPackageRoot = resolve(dirname(require.resolve('@treeseed/sdk')), '..');
|
|
10
|
+
const npmCacheDir = resolve(tmpdir(), 'treeseed-npm-cache');
|
|
10
11
|
function run(command, args, cwd = packageRoot, capture = false) {
|
|
11
12
|
const result = spawnSync(command, args, {
|
|
12
13
|
cwd,
|
|
13
14
|
stdio: capture ? 'pipe' : 'inherit',
|
|
14
15
|
encoding: 'utf8',
|
|
15
|
-
env:
|
|
16
|
+
env: {
|
|
17
|
+
...process.env,
|
|
18
|
+
npm_config_cache: npmCacheDir,
|
|
19
|
+
NPM_CONFIG_CACHE: npmCacheDir,
|
|
20
|
+
},
|
|
16
21
|
});
|
|
17
22
|
if (result.status !== 0) {
|
|
18
23
|
throw new Error(result.stderr?.trim() || result.stdout?.trim() || `${command} ${args.join(' ')} failed`);
|
|
@@ -61,12 +66,18 @@ function pack(root, outputRoot, fallbackName) {
|
|
|
61
66
|
return bundledTarball;
|
|
62
67
|
}
|
|
63
68
|
mkdirSync(outputRoot, { recursive: true });
|
|
64
|
-
const output = run('npm', ['pack', '--
|
|
69
|
+
const output = run('npm', ['pack', '--ignore-scripts', '--cache', npmCacheDir, '--pack-destination', outputRoot], root, true);
|
|
65
70
|
const filename = output
|
|
66
71
|
.split('\n')
|
|
67
72
|
.map((line) => line.trim())
|
|
68
73
|
.filter(Boolean)
|
|
69
|
-
.at(-1)
|
|
74
|
+
.at(-1)
|
|
75
|
+
?? readdirSync(outputRoot, { withFileTypes: true })
|
|
76
|
+
.filter((entry) => entry.isFile() && entry.name.endsWith('.tgz'))
|
|
77
|
+
.map((entry) => entry.name)
|
|
78
|
+
.sort((left, right) => left.localeCompare(right, undefined, { numeric: true, sensitivity: 'base' }))
|
|
79
|
+
.at(-1)
|
|
80
|
+
?? fallbackName;
|
|
70
81
|
return resolve(outputRoot, filename);
|
|
71
82
|
}
|
|
72
83
|
function installPackageDirectory(tempRoot, packageRoot, folderName) {
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, realpathSync, rmSync, symlinkSync } from 'node:fs';
|
|
3
|
+
import { dirname, resolve } from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { spawnSync } from 'node:child_process';
|
|
6
|
+
import { createRequire } from 'node:module';
|
|
7
|
+
import { packageRoot } from './package-tools.js';
|
|
8
|
+
const require = createRequire(import.meta.url);
|
|
9
|
+
const requiredPackages = [
|
|
10
|
+
{ name: '@treeseed/sdk', dir: 'packages/sdk', build: true },
|
|
11
|
+
{ name: '@treeseed/core', dir: 'packages/core', build: true },
|
|
12
|
+
{ name: '@treeseed/agent', dir: 'packages/agent', build: true },
|
|
13
|
+
{ name: '@treeseed/api', dir: 'packages/api', build: true },
|
|
14
|
+
{ name: '@treeseed/cli', dir: 'packages/cli', build: true, binName: 'treeseed' },
|
|
15
|
+
];
|
|
16
|
+
function packageState(root, entry) {
|
|
17
|
+
const dir = resolve(root, entry.dir);
|
|
18
|
+
const packageJsonPath = resolve(dir, 'package.json');
|
|
19
|
+
return {
|
|
20
|
+
...entry,
|
|
21
|
+
dir,
|
|
22
|
+
relativeDir: entry.dir,
|
|
23
|
+
packageJsonPath,
|
|
24
|
+
present: existsSync(dir) && existsSync(packageJsonPath),
|
|
25
|
+
dirExists: existsSync(dir),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export function detectTreeseedBootstrapMode(startRoot = process.cwd()) {
|
|
29
|
+
const root = resolve(startRoot);
|
|
30
|
+
const forcedMode = process.env.TREESEED_BOOTSTRAP_MODE;
|
|
31
|
+
if (forcedMode === 'workspace' || forcedMode === 'registry') {
|
|
32
|
+
const packages = requiredPackages.map((entry) => packageState(root, entry));
|
|
33
|
+
return {
|
|
34
|
+
mode: forcedMode,
|
|
35
|
+
packages,
|
|
36
|
+
missing: packages.filter((entry) => !entry.present),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
const packages = requiredPackages.map((entry) => packageState(root, entry));
|
|
40
|
+
const present = packages.filter((entry) => entry.present);
|
|
41
|
+
const partial = present.length > 0 && present.length < packages.length;
|
|
42
|
+
if (partial) {
|
|
43
|
+
return {
|
|
44
|
+
mode: 'partial',
|
|
45
|
+
packages,
|
|
46
|
+
missing: packages.filter((entry) => !entry.present),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
mode: present.length === packages.length ? 'workspace' : 'registry',
|
|
51
|
+
packages,
|
|
52
|
+
missing: packages.filter((entry) => !entry.present),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function run(command, args, options = {}) {
|
|
56
|
+
const result = spawnSync(command, args, {
|
|
57
|
+
cwd: options.cwd,
|
|
58
|
+
env: { ...process.env, ...(options.env ?? {}) },
|
|
59
|
+
stdio: 'inherit',
|
|
60
|
+
encoding: 'utf8',
|
|
61
|
+
});
|
|
62
|
+
if (result.status !== 0) {
|
|
63
|
+
const rendered = [command, ...args].join(' ');
|
|
64
|
+
throw new Error(`Command failed: ${rendered}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function resolvePackageBinary(packageName, binName = packageName, root = process.cwd()) {
|
|
68
|
+
const packageJsonPath = require.resolve(`${packageName}/package.json`, { paths: [root, packageRoot] });
|
|
69
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
|
|
70
|
+
const binField = packageJson.bin;
|
|
71
|
+
const relativePath = typeof binField === 'string' ? binField : binField?.[binName];
|
|
72
|
+
if (!relativePath) {
|
|
73
|
+
throw new Error(`Unable to resolve binary "${binName}" from package "${packageName}".`);
|
|
74
|
+
}
|
|
75
|
+
return resolve(dirname(packageJsonPath), relativePath);
|
|
76
|
+
}
|
|
77
|
+
function runStarlightPatchFromRegistry(root) {
|
|
78
|
+
const corePackageJsonPath = require.resolve('@treeseed/core/package.json', { paths: [root, packageRoot] });
|
|
79
|
+
const coreRoot = dirname(corePackageJsonPath);
|
|
80
|
+
const patchScriptPath = resolve(coreRoot, 'dist', 'scripts', 'patch-starlight-content-path.js');
|
|
81
|
+
if (existsSync(patchScriptPath)) {
|
|
82
|
+
run(process.execPath, [patchScriptPath], { cwd: root });
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const treeseedBin = resolvePackageBinary('@treeseed/cli', 'treeseed', root);
|
|
86
|
+
run(process.execPath, [treeseedBin, 'starlight:patch'], { cwd: root });
|
|
87
|
+
}
|
|
88
|
+
function runStarlightPatchFromWorkspace(root, packages) {
|
|
89
|
+
const corePackage = packages.find((entry) => entry.name === '@treeseed/core');
|
|
90
|
+
run(process.execPath, [resolve(corePackage.dir, 'scripts/run-ts.mjs'), resolve(corePackage.dir, 'scripts/patch-starlight-content-path.ts')], { cwd: root });
|
|
91
|
+
}
|
|
92
|
+
function linkWorkspacePackages(root, packages) {
|
|
93
|
+
for (const targetRoot of [root, ...packages.map((entry) => entry.dir)]) {
|
|
94
|
+
const scopeRoot = resolve(targetRoot, 'node_modules/@treeseed');
|
|
95
|
+
mkdirSync(scopeRoot, { recursive: true });
|
|
96
|
+
for (const entry of packages) {
|
|
97
|
+
const linkPath = resolve(scopeRoot, entry.name.replace('@treeseed/', ''));
|
|
98
|
+
if (resolve(linkPath) === resolve(entry.dir)) {
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
rmSync(linkPath, { recursive: true, force: true });
|
|
102
|
+
symlinkSync(entry.dir, linkPath, 'dir');
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
function printPartialError(state) {
|
|
107
|
+
const missing = state.missing.map((entry) => ` - ${entry.relativeDir}`).join('\n');
|
|
108
|
+
console.error('Treeseed bootstrap found a partial package checkout.');
|
|
109
|
+
console.error('');
|
|
110
|
+
console.error('Either initialize all Treeseed package submodules:');
|
|
111
|
+
console.error(' git submodule update --init --recursive');
|
|
112
|
+
console.error('');
|
|
113
|
+
console.error('Or remove the partial package checkout and use registry mode.');
|
|
114
|
+
console.error('');
|
|
115
|
+
console.error(`Missing package manifests:\n${missing}`);
|
|
116
|
+
}
|
|
117
|
+
export function runTreeseedWorkspaceBootstrap({ root = process.cwd() } = {}) {
|
|
118
|
+
const resolvedRoot = resolve(root);
|
|
119
|
+
const state = detectTreeseedBootstrapMode(resolvedRoot);
|
|
120
|
+
if (state.mode === 'partial') {
|
|
121
|
+
printPartialError(state);
|
|
122
|
+
return 1;
|
|
123
|
+
}
|
|
124
|
+
if (state.mode === 'workspace') {
|
|
125
|
+
console.log('Treeseed bootstrap mode: workspace (using checked-out packages/* submodules)');
|
|
126
|
+
linkWorkspacePackages(resolvedRoot, state.packages);
|
|
127
|
+
for (const entry of state.packages.filter((pkg) => pkg.build)) {
|
|
128
|
+
run('npm', ['--prefix', entry.dir, 'run', 'build:dist'], { cwd: resolvedRoot });
|
|
129
|
+
}
|
|
130
|
+
runStarlightPatchFromWorkspace(resolvedRoot, state.packages);
|
|
131
|
+
return 0;
|
|
132
|
+
}
|
|
133
|
+
console.log('Treeseed bootstrap mode: registry (using published @treeseed/* packages)');
|
|
134
|
+
runStarlightPatchFromRegistry(resolvedRoot);
|
|
135
|
+
return 0;
|
|
136
|
+
}
|
|
137
|
+
function isDirectEntrypoint() {
|
|
138
|
+
if (!process.argv[1]) {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
const invokedPath = realpathSync(resolve(process.argv[1]));
|
|
142
|
+
const modulePath = realpathSync(fileURLToPath(import.meta.url));
|
|
143
|
+
return modulePath === invokedPath || invokedPath.endsWith('/scripts/workspace-bootstrap.ts');
|
|
144
|
+
}
|
|
145
|
+
if (isDirectEntrypoint()) {
|
|
146
|
+
try {
|
|
147
|
+
process.exitCode = runTreeseedWorkspaceBootstrap();
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
151
|
+
process.exitCode = 1;
|
|
152
|
+
}
|
|
153
|
+
}
|
package/dist/tenant/config.js
CHANGED
|
@@ -1,119 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
}
|
|
10
|
-
return resolve(dirname(fileURLToPath(moduleUrl)), "../..");
|
|
11
|
-
}
|
|
12
|
-
const packageRoot = resolvePackageRoot();
|
|
13
|
-
const packageFixtureRoot = resolve(packageRoot, ".fixtures", "treeseed-fixtures", "sites", "working-site");
|
|
14
|
-
const explicitTenantRoot = process.env.TREESEED_TENANT_ROOT ? resolve(process.env.TREESEED_TENANT_ROOT) : null;
|
|
15
|
-
function pathWithin(parent, candidate) {
|
|
16
|
-
const normalizedParent = resolve(parent);
|
|
17
|
-
const normalizedCandidate = resolve(candidate);
|
|
18
|
-
return normalizedCandidate === normalizedParent || normalizedCandidate.startsWith(`${normalizedParent}/`);
|
|
19
|
-
}
|
|
20
|
-
function collectTenantRootCandidates(start) {
|
|
21
|
-
const candidates = [];
|
|
22
|
-
let current = resolve(start);
|
|
23
|
-
while (true) {
|
|
24
|
-
candidates.push(
|
|
25
|
-
current,
|
|
26
|
-
resolve(current, ".fixtures", "treeseed-fixtures", "sites", "working-site"),
|
|
27
|
-
resolve(current, "fixture")
|
|
28
|
-
);
|
|
29
|
-
const parent = resolve(current, "..");
|
|
30
|
-
if (parent === current) {
|
|
31
|
-
break;
|
|
32
|
-
}
|
|
33
|
-
current = parent;
|
|
34
|
-
}
|
|
35
|
-
return candidates;
|
|
36
|
-
}
|
|
37
|
-
function uniqueCandidates(entries) {
|
|
38
|
-
return [...new Set(entries.map((entry) => resolve(entry)))];
|
|
39
|
-
}
|
|
40
|
-
function tenantRootCandidates() {
|
|
41
|
-
const cwd = resolve(process.cwd());
|
|
42
|
-
const cwdCandidates = collectTenantRootCandidates(cwd);
|
|
43
|
-
const packageCandidates = collectTenantRootCandidates(packageRoot);
|
|
44
|
-
if (explicitTenantRoot) {
|
|
45
|
-
return uniqueCandidates([explicitTenantRoot, ...cwdCandidates, packageFixtureRoot, ...packageCandidates]);
|
|
46
|
-
}
|
|
47
|
-
if (pathWithin(packageRoot, cwd)) {
|
|
48
|
-
return uniqueCandidates([packageFixtureRoot, ...cwdCandidates, ...packageCandidates]);
|
|
49
|
-
}
|
|
50
|
-
return uniqueCandidates([...cwdCandidates, packageFixtureRoot, ...packageCandidates]);
|
|
51
|
-
}
|
|
52
|
-
function resolveTenantPath(manifestPath) {
|
|
53
|
-
if (existsSync(manifestPath)) {
|
|
54
|
-
return resolve(manifestPath);
|
|
55
|
-
}
|
|
56
|
-
const candidates = tenantRootCandidates().map((root) => resolve(root, manifestPath));
|
|
57
|
-
for (const candidate of candidates) {
|
|
58
|
-
if (existsSync(candidate)) {
|
|
59
|
-
return candidate;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
throw new Error(
|
|
63
|
-
`Unable to resolve Treeseed tenant manifest at "${manifestPath}" from ${process.cwd()} or ${packageFixtureRoot}.`
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
function resolveTenantRoot() {
|
|
67
|
-
const candidates = tenantRootCandidates();
|
|
68
|
-
for (const candidate of candidates) {
|
|
69
|
-
if (existsSync(resolve(candidate, "src/manifest.yaml"))) {
|
|
70
|
-
return candidate;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
throw new Error(
|
|
74
|
-
`Unable to resolve a Treeseed tenant root from ${process.cwd()} or ${packageFixtureRoot}.`
|
|
75
|
-
);
|
|
76
|
-
}
|
|
77
|
-
function defineTreeseedTenant(tenantConfig) {
|
|
78
|
-
return tenantConfig;
|
|
79
|
-
}
|
|
80
|
-
function loadTreeseedManifest(manifestPath = "./src/manifest.yaml") {
|
|
81
|
-
const resolvedManifestPath = resolveTenantPath(manifestPath);
|
|
82
|
-
const tenantRoot = resolve(dirname(resolvedManifestPath), "..");
|
|
83
|
-
const parsed = parseYaml(readFileSync(resolvedManifestPath, "utf8"));
|
|
84
|
-
const tenantConfig = defineTreeseedTenant({
|
|
85
|
-
...parsed,
|
|
86
|
-
siteConfigPath: resolve(tenantRoot, parsed.siteConfigPath),
|
|
87
|
-
content: Object.fromEntries(
|
|
88
|
-
Object.entries(parsed.content ?? {}).map(([collectionName, rootPath]) => [
|
|
89
|
-
collectionName,
|
|
90
|
-
resolve(tenantRoot, String(rootPath))
|
|
91
|
-
])
|
|
92
|
-
),
|
|
93
|
-
overrides: parsed.overrides ? {
|
|
94
|
-
pagesRoot: parsed.overrides.pagesRoot ? resolve(tenantRoot, parsed.overrides.pagesRoot) : void 0,
|
|
95
|
-
stylesRoot: parsed.overrides.stylesRoot ? resolve(tenantRoot, parsed.overrides.stylesRoot) : void 0,
|
|
96
|
-
componentsRoot: parsed.overrides.componentsRoot ? resolve(tenantRoot, parsed.overrides.componentsRoot) : void 0
|
|
97
|
-
} : void 0
|
|
98
|
-
});
|
|
99
|
-
Object.defineProperty(tenantConfig, "__tenantRoot", {
|
|
100
|
-
value: tenantRoot,
|
|
101
|
-
enumerable: false
|
|
102
|
-
});
|
|
103
|
-
return tenantConfig;
|
|
104
|
-
}
|
|
105
|
-
const loadTreeseedTenantManifest = loadTreeseedManifest;
|
|
106
|
-
const resolveTreeseedTenantRoot = resolveTenantRoot;
|
|
107
|
-
function getTenantContentRoot(tenantConfig, collectionName) {
|
|
108
|
-
const root = tenantConfig.content[collectionName];
|
|
109
|
-
if (!root) {
|
|
110
|
-
throw new Error(`Unknown tenant content collection: ${collectionName}`);
|
|
111
|
-
}
|
|
112
|
-
return root;
|
|
113
|
-
}
|
|
114
|
-
function tenantFeatureEnabled(tenantConfig, featureName) {
|
|
115
|
-
return tenantConfig.features?.[featureName] !== false;
|
|
116
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
defineTreeseedTenant,
|
|
3
|
+
getTenantContentRoot,
|
|
4
|
+
loadTreeseedManifest,
|
|
5
|
+
loadTreeseedTenantManifest,
|
|
6
|
+
resolveTreeseedTenantRoot,
|
|
7
|
+
tenantFeatureEnabled
|
|
8
|
+
} from "@treeseed/sdk/platform/tenant-config";
|
|
117
9
|
export {
|
|
118
10
|
defineTreeseedTenant,
|
|
119
11
|
getTenantContentRoot,
|
|
@@ -1,88 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
questionId: string;
|
|
3
|
-
reason: string;
|
|
4
|
-
plannerRunId: string;
|
|
5
|
-
}
|
|
6
|
-
export interface ObjectivePriorityUpdatedMessage {
|
|
7
|
-
objectiveId: string;
|
|
8
|
-
reason: string;
|
|
9
|
-
plannerRunId: string;
|
|
10
|
-
}
|
|
11
|
-
export interface ArchitectureUpdatedMessage {
|
|
12
|
-
objectiveId: string;
|
|
13
|
-
knowledgeId: string;
|
|
14
|
-
architectRunId: string;
|
|
15
|
-
}
|
|
16
|
-
export interface SubscriberNotifiedMessage {
|
|
17
|
-
email: string;
|
|
18
|
-
itemCount: number;
|
|
19
|
-
notifierRunId: string;
|
|
20
|
-
}
|
|
21
|
-
export interface ResearchStartedMessage {
|
|
22
|
-
questionId: string;
|
|
23
|
-
researcherRunId: string;
|
|
24
|
-
}
|
|
25
|
-
export interface ResearchCompletedMessage {
|
|
26
|
-
questionId: string;
|
|
27
|
-
knowledgeId: string | null;
|
|
28
|
-
researcherRunId: string;
|
|
29
|
-
}
|
|
30
|
-
export interface TaskCompleteMessage {
|
|
31
|
-
branchName: string | null;
|
|
32
|
-
changedTargets: string[];
|
|
33
|
-
engineerRunId: string;
|
|
34
|
-
}
|
|
35
|
-
export interface TaskWaitingMessage {
|
|
36
|
-
blockingReason: string;
|
|
37
|
-
engineerRunId: string;
|
|
38
|
-
}
|
|
39
|
-
export interface TaskFailedMessage {
|
|
40
|
-
failureSummary: string;
|
|
41
|
-
engineerRunId: string;
|
|
42
|
-
}
|
|
43
|
-
export interface TaskVerifiedMessage {
|
|
44
|
-
branchName: string | null;
|
|
45
|
-
reviewerRunId: string;
|
|
46
|
-
}
|
|
47
|
-
export interface ReviewFailedMessage {
|
|
48
|
-
failureSummary: string;
|
|
49
|
-
reviewerRunId: string;
|
|
50
|
-
}
|
|
51
|
-
export interface ReviewWaitingMessage {
|
|
52
|
-
blockingReason: string;
|
|
53
|
-
reviewerRunId: string;
|
|
54
|
-
}
|
|
55
|
-
export interface ReleaseStartedMessage {
|
|
56
|
-
taskRunId: string | null;
|
|
57
|
-
releaserRunId: string;
|
|
58
|
-
}
|
|
59
|
-
export interface ReleaseCompletedMessage {
|
|
60
|
-
releaseSummary: string;
|
|
61
|
-
releaserRunId: string;
|
|
62
|
-
}
|
|
63
|
-
export interface ReleaseFailedMessage {
|
|
64
|
-
failureSummary: string;
|
|
65
|
-
releaserRunId: string;
|
|
66
|
-
}
|
|
67
|
-
export interface AgentMessageContracts {
|
|
68
|
-
question_priority_updated: QuestionPriorityUpdatedMessage;
|
|
69
|
-
objective_priority_updated: ObjectivePriorityUpdatedMessage;
|
|
70
|
-
architecture_updated: ArchitectureUpdatedMessage;
|
|
71
|
-
subscriber_notified: SubscriberNotifiedMessage;
|
|
72
|
-
research_started: ResearchStartedMessage;
|
|
73
|
-
research_completed: ResearchCompletedMessage;
|
|
74
|
-
task_complete: TaskCompleteMessage;
|
|
75
|
-
task_waiting: TaskWaitingMessage;
|
|
76
|
-
task_failed: TaskFailedMessage;
|
|
77
|
-
task_verified: TaskVerifiedMessage;
|
|
78
|
-
review_failed: ReviewFailedMessage;
|
|
79
|
-
review_waiting: ReviewWaitingMessage;
|
|
80
|
-
release_started: ReleaseStartedMessage;
|
|
81
|
-
release_completed: ReleaseCompletedMessage;
|
|
82
|
-
release_failed: ReleaseFailedMessage;
|
|
83
|
-
}
|
|
84
|
-
export type AgentMessageType = keyof AgentMessageContracts;
|
|
85
|
-
export type AgentMessagePayload<TType extends AgentMessageType> = AgentMessageContracts[TType];
|
|
86
|
-
export declare const AGENT_MESSAGE_TYPES: readonly ["question_priority_updated", "objective_priority_updated", "architecture_updated", "subscriber_notified", "research_started", "research_completed", "task_complete", "task_waiting", "task_failed", "task_verified", "review_failed", "review_waiting", "release_started", "release_completed", "release_failed"];
|
|
87
|
-
export declare function parseAgentMessagePayload<TType extends AgentMessageType>(type: TType, payloadJson: string): AgentMessagePayload<TType>;
|
|
88
|
-
export declare function serializeAgentMessagePayload<TType extends AgentMessageType>(type: TType, payload: AgentMessagePayload<TType>): Record<string, unknown>;
|
|
1
|
+
export * from '@treeseed/sdk/utils/agents/contracts/messages';
|