@treeseed/core 0.5.3 → 0.6.1
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/agent-runtime.js +10 -4
- package/dist/api/agent-routes.js +22 -5
- package/dist/content.js +11 -3
- package/dist/env.yaml +11 -9
- package/dist/middleware/starlightRouteData.js +20 -5
- package/dist/services/worker-pool-scaler.js +1 -1
- package/dist/tenant/runtime-config.js +33 -24
- package/dist/utils/published-content.js +1 -1
- package/dist/utils/site-models.d.ts +2 -2
- package/dist/utils/site-models.js +3 -2
- package/dist/utils/starlight-nav.js +13 -6
- package/package.json +2 -2
package/dist/agent-runtime.js
CHANGED
|
@@ -5,9 +5,9 @@ import {
|
|
|
5
5
|
StubExecutionAdapter
|
|
6
6
|
} from "./agents/adapters/execution.js";
|
|
7
7
|
import { LocalBranchMutationAdapter } from "./agents/adapters/mutations.js";
|
|
8
|
-
import { StubNotificationAdapter } from "./agents/adapters/notification.js";
|
|
8
|
+
import { SdkMessageNotificationAdapter, StubNotificationAdapter } from "./agents/adapters/notification.js";
|
|
9
9
|
import { GitRepositoryInspectionAdapter, StubRepositoryInspectionAdapter } from "./agents/adapters/repository.js";
|
|
10
|
-
import { StubResearchAdapter } from "./agents/adapters/research.js";
|
|
10
|
+
import { ProjectGraphResearchAdapter, StubResearchAdapter } from "./agents/adapters/research.js";
|
|
11
11
|
import { LocalVerificationAdapter, StubVerificationAdapter } from "./agents/adapters/verification.js";
|
|
12
12
|
let cachedAgentRuntime = null;
|
|
13
13
|
function readPluginRecord(pluginEntry, key) {
|
|
@@ -44,8 +44,14 @@ function buildAgentRuntime() {
|
|
|
44
44
|
["stub", () => new StubVerificationAdapter()],
|
|
45
45
|
["local", () => new LocalVerificationAdapter()]
|
|
46
46
|
]);
|
|
47
|
-
const notification = /* @__PURE__ */ new Map([
|
|
48
|
-
|
|
47
|
+
const notification = /* @__PURE__ */ new Map([
|
|
48
|
+
["stub", () => new StubNotificationAdapter()],
|
|
49
|
+
["sdk_message", () => new SdkMessageNotificationAdapter()]
|
|
50
|
+
]);
|
|
51
|
+
const research = /* @__PURE__ */ new Map([
|
|
52
|
+
["stub", () => new StubResearchAdapter()],
|
|
53
|
+
["project_graph", () => new ProjectGraphResearchAdapter()]
|
|
54
|
+
]);
|
|
49
55
|
const handlers = /* @__PURE__ */ new Map();
|
|
50
56
|
for (const pluginEntry of runtime.plugins) {
|
|
51
57
|
const agentProviders = readPluginRecord(pluginEntry, "agentProviders");
|
package/dist/api/agent-routes.js
CHANGED
|
@@ -4,6 +4,19 @@ import { jsonError, requireScope } from "./http.js";
|
|
|
4
4
|
async function listRegisteredHandlers() {
|
|
5
5
|
return listCoreRegisteredAgentHandlers();
|
|
6
6
|
}
|
|
7
|
+
async function safeListRegisteredHandlers() {
|
|
8
|
+
try {
|
|
9
|
+
return {
|
|
10
|
+
handlers: await listRegisteredHandlers(),
|
|
11
|
+
error: null
|
|
12
|
+
};
|
|
13
|
+
} catch (error) {
|
|
14
|
+
return {
|
|
15
|
+
handlers: [],
|
|
16
|
+
error: error instanceof Error ? error.message : String(error)
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
}
|
|
7
20
|
function withPrefix(prefix, path) {
|
|
8
21
|
return `${prefix}${path}`.replace(/\/{2,}/g, "/");
|
|
9
22
|
}
|
|
@@ -23,11 +36,15 @@ function authorizeRequest(c, options) {
|
|
|
23
36
|
function registerAgentRoutes(app, options) {
|
|
24
37
|
const prefix = options.prefix ?? "/agent";
|
|
25
38
|
const defaultActor = options.defaultActor ?? "api";
|
|
26
|
-
app.get(withPrefix(prefix, "/healthz"), async (c) =>
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
39
|
+
app.get(withPrefix(prefix, "/healthz"), async (c) => {
|
|
40
|
+
const registration = await safeListRegisteredHandlers();
|
|
41
|
+
return c.json({
|
|
42
|
+
ok: true,
|
|
43
|
+
service: "treeseed-agent-api",
|
|
44
|
+
handlerCount: registration.handlers.length,
|
|
45
|
+
registrationError: registration.error
|
|
46
|
+
});
|
|
47
|
+
});
|
|
31
48
|
app.get(withPrefix(prefix, "/specs"), async (c) => {
|
|
32
49
|
const unauthorized = authorizeRequest(c, options);
|
|
33
50
|
if (unauthorized) return unauthorized;
|
package/dist/content.js
CHANGED
|
@@ -28,6 +28,7 @@ const timeHorizonValues = ["near-term", "mid-term", "long-term"];
|
|
|
28
28
|
const runtimeStatusValues = ["active", "experimental", "dormant"];
|
|
29
29
|
const agentTriggerTypeValues = ["schedule", "message", "follow", "startup"];
|
|
30
30
|
const agentPermissionOperationValues = ["get", "search", "follow", "pick", "create", "update"];
|
|
31
|
+
const treeseedDocsExtensions = ["markdown", "mdown", "mkdn", "mkd", "mdwn", "md", "mdx"];
|
|
31
32
|
function hasMarkdownContent(base) {
|
|
32
33
|
if (!existsSync(base)) {
|
|
33
34
|
return false;
|
|
@@ -39,8 +40,12 @@ function hasMarkdownContent(base) {
|
|
|
39
40
|
}
|
|
40
41
|
return false;
|
|
41
42
|
}
|
|
42
|
-
function optionalMarkdownGlob(base) {
|
|
43
|
-
const delegate = glob({
|
|
43
|
+
function optionalMarkdownGlob(base, options = {}) {
|
|
44
|
+
const delegate = glob({
|
|
45
|
+
pattern: options.pattern ?? "**/*.{md,mdx}",
|
|
46
|
+
base,
|
|
47
|
+
generateId: options.generateId
|
|
48
|
+
});
|
|
44
49
|
return {
|
|
45
50
|
name: `treeseed-optional-markdown-glob:${base}`,
|
|
46
51
|
async load(context) {
|
|
@@ -68,7 +73,10 @@ function resolveDocsCollectionProvider(tenantConfig, dependencies) {
|
|
|
68
73
|
const selectedId = pluginRuntime.config.providers.content.docs;
|
|
69
74
|
if (selectedId === "default") {
|
|
70
75
|
return {
|
|
71
|
-
loader:
|
|
76
|
+
loader: optionalMarkdownGlob(tenantConfig.content.docs, {
|
|
77
|
+
pattern: `**/[^_]*.{${treeseedDocsExtensions.join(",")}}`,
|
|
78
|
+
generateId: createKnowledgeDocId
|
|
79
|
+
}),
|
|
72
80
|
schema: dependencies.docsSchema({
|
|
73
81
|
extend: z.object({
|
|
74
82
|
tags: z.array(z.string()).default(TREESEED_MODEL_DEFAULTS.tags ?? [])
|
package/dist/env.yaml
CHANGED
|
@@ -73,31 +73,33 @@ entries:
|
|
|
73
73
|
- process-env
|
|
74
74
|
relevanceRef: railwayManagedEnabled
|
|
75
75
|
requiredWhenRef: railwayManagedEnabled
|
|
76
|
-
|
|
77
|
-
label: Railway
|
|
78
|
-
group:
|
|
79
|
-
description:
|
|
80
|
-
howToGet: In Railway,
|
|
81
|
-
sensitivity:
|
|
76
|
+
TREESEED_RAILWAY_WORKSPACE:
|
|
77
|
+
label: Railway workspace
|
|
78
|
+
group: railway
|
|
79
|
+
description: Railway workspace Treeseed should use when listing or creating projects during bootstrap and config reconciliation.
|
|
80
|
+
howToGet: In Railway, use the workspace slug or name shown in the workspace switcher. Treeseed defaults this repository to knowledge-coop unless you override it here.
|
|
81
|
+
sensitivity: plain
|
|
82
82
|
targets:
|
|
83
83
|
- local-runtime
|
|
84
|
-
- railway-
|
|
84
|
+
- railway-var
|
|
85
85
|
scopes:
|
|
86
86
|
- local
|
|
87
87
|
- staging
|
|
88
88
|
- prod
|
|
89
|
-
|
|
89
|
+
storage: shared
|
|
90
|
+
requirement: conditional
|
|
90
91
|
purposes:
|
|
91
92
|
- deploy
|
|
92
93
|
- destroy
|
|
93
94
|
- config
|
|
94
95
|
validation:
|
|
95
96
|
kind: nonempty
|
|
96
|
-
minLength: 8
|
|
97
97
|
sourcePriority:
|
|
98
98
|
- machine-config
|
|
99
99
|
- process-env
|
|
100
|
+
defaultValueRef: railwayWorkspaceDefault
|
|
100
101
|
relevanceRef: railwayManagedEnabled
|
|
102
|
+
requiredWhenRef: railwayManagedEnabled
|
|
101
103
|
CLOUDFLARE_ACCOUNT_ID:
|
|
102
104
|
label: Cloudflare account ID
|
|
103
105
|
group: cloudflare
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { defineRouteMiddleware } from "../vendor/starlight/route-data.js";
|
|
2
2
|
import { TREESEED_LINKS, buildStarlightSidebarEntriesFromRuntime, normalizeHref } from "../utils/starlight-nav.js";
|
|
3
3
|
import { loadHostedBookRuntime } from "../utils/published-content.js";
|
|
4
|
-
import {
|
|
5
|
-
import { loadTreeseedManifest, tenantModelRendered } from "@treeseed/sdk/platform/tenant-config";
|
|
4
|
+
import { RUNTIME_TENANT } from "../tenant/runtime-config.js";
|
|
6
5
|
const copyLink = (entry) => ({ ...entry, attrs: { ...entry.attrs } });
|
|
7
6
|
const copyEntry = (entry) => entry.type === "link" ? copyLink(entry) : {
|
|
8
7
|
...entry,
|
|
@@ -26,12 +25,28 @@ const setRouteSidebar = (route, currentPath, sidebar, paginationSource) => {
|
|
|
26
25
|
route.hasSidebar = sidebar.length > 0;
|
|
27
26
|
route.pagination = paginationSource ? buildPagination(paginationSource, currentPath) : { prev: void 0, next: void 0 };
|
|
28
27
|
};
|
|
29
|
-
const defaultRuntime = {
|
|
30
|
-
|
|
28
|
+
const defaultRuntime = {
|
|
29
|
+
BOOKS: [],
|
|
30
|
+
BOOKS_LINK: {
|
|
31
|
+
label: "Books",
|
|
32
|
+
link: TREESEED_LINKS.home
|
|
33
|
+
},
|
|
34
|
+
TREESEED_LIBRARY_DOWNLOAD: {
|
|
35
|
+
downloadFileName: "treeseed-knowledge.md",
|
|
36
|
+
downloadHref: "/books/treeseed-knowledge.md",
|
|
37
|
+
downloadTitle: "TreeSeed Knowledge Library"
|
|
38
|
+
},
|
|
39
|
+
TREESEED_LINKS
|
|
40
|
+
};
|
|
41
|
+
function runtimeTenantModelRendered(modelName) {
|
|
42
|
+
const featureValue = RUNTIME_TENANT.features?.[modelName];
|
|
43
|
+
const siteValue = RUNTIME_TENANT.site?.[modelName];
|
|
44
|
+
return featureValue ?? siteValue ?? true;
|
|
45
|
+
}
|
|
31
46
|
const onRequest = defineRouteMiddleware(async (context) => {
|
|
32
47
|
const route = context.locals.starlightRoute;
|
|
33
48
|
const currentPath = normalizeHref(context.url.pathname);
|
|
34
|
-
if (!
|
|
49
|
+
if (!runtimeTenantModelRendered("books")) {
|
|
35
50
|
setRouteSidebar(route, currentPath, [], null);
|
|
36
51
|
return;
|
|
37
52
|
}
|
|
@@ -35,7 +35,7 @@ class RailwayWorkerPoolScaler {
|
|
|
35
35
|
fetchImpl;
|
|
36
36
|
mutation;
|
|
37
37
|
constructor(options = {}) {
|
|
38
|
-
this.apiToken = options.apiToken?.trim() || envValue("RAILWAY_API_TOKEN") ||
|
|
38
|
+
this.apiToken = options.apiToken?.trim() || envValue("RAILWAY_API_TOKEN") || null;
|
|
39
39
|
this.apiUrl = options.apiUrl?.trim() || envValue("TREESEED_RAILWAY_API_URL") || DEFAULT_RAILWAY_API_URL;
|
|
40
40
|
this.serviceId = options.serviceId?.trim() || envValue("TREESEED_RAILWAY_WORKER_SERVICE_ID") || envValue("TREESEED_WORKER_SERVICE_ID") || null;
|
|
41
41
|
this.environmentId = options.environmentId?.trim() || envValue("TREESEED_RAILWAY_ENVIRONMENT_ID") || null;
|
|
@@ -1,29 +1,38 @@
|
|
|
1
|
-
import { readFileSync } from "node:fs";
|
|
2
|
-
import { resolve } from "node:path";
|
|
3
|
-
import { loadTreeseedManifest } from "@treeseed/sdk/platform/tenant-config";
|
|
4
1
|
import { parseSiteConfig } from "../utils/site-config-schema.js";
|
|
5
2
|
const injectedTenantConfig = typeof __TREESEED_TENANT_CONFIG__ !== "undefined" ? __TREESEED_TENANT_CONFIG__ : null;
|
|
6
3
|
const injectedProjectRoot = typeof __TREESEED_PROJECT_ROOT__ !== "undefined" ? __TREESEED_PROJECT_ROOT__ : null;
|
|
7
4
|
const injectedSiteConfig = typeof __TREESEED_SITE_CONFIG__ !== "undefined" ? __TREESEED_SITE_CONFIG__ : null;
|
|
8
|
-
|
|
5
|
+
function getNodeBuiltin(name) {
|
|
6
|
+
const getBuiltinModule = globalThis.process?.getBuiltinModule;
|
|
7
|
+
return getBuiltinModule?.(name) ?? null;
|
|
8
|
+
}
|
|
9
|
+
function getCwd() {
|
|
10
|
+
const cwd = globalThis.process?.cwd;
|
|
11
|
+
return cwd?.() ?? ".";
|
|
12
|
+
}
|
|
13
|
+
function resolveRuntimePath(projectRoot, path) {
|
|
14
|
+
const pathModule = getNodeBuiltin("path");
|
|
15
|
+
return pathModule?.resolve(projectRoot, path) ?? `${projectRoot.replace(/\/$/, "")}/${path}`;
|
|
16
|
+
}
|
|
17
|
+
const RUNTIME_PROJECT_ROOT = injectedProjectRoot ?? getCwd();
|
|
9
18
|
function fallbackTenantConfig(projectRoot) {
|
|
10
19
|
return {
|
|
11
20
|
id: "treeseed-runtime",
|
|
12
|
-
siteConfigPath:
|
|
21
|
+
siteConfigPath: resolveRuntimePath(projectRoot, "treeseed.site.yaml"),
|
|
13
22
|
content: {
|
|
14
|
-
pages:
|
|
15
|
-
notes:
|
|
16
|
-
questions:
|
|
17
|
-
objectives:
|
|
18
|
-
proposals:
|
|
19
|
-
decisions:
|
|
20
|
-
people:
|
|
21
|
-
agents:
|
|
22
|
-
books:
|
|
23
|
-
docs:
|
|
24
|
-
templates:
|
|
25
|
-
knowledge_packs:
|
|
26
|
-
workdays:
|
|
23
|
+
pages: resolveRuntimePath(projectRoot, "src/content/pages"),
|
|
24
|
+
notes: resolveRuntimePath(projectRoot, "src/content/notes"),
|
|
25
|
+
questions: resolveRuntimePath(projectRoot, "src/content/questions"),
|
|
26
|
+
objectives: resolveRuntimePath(projectRoot, "src/content/objectives"),
|
|
27
|
+
proposals: resolveRuntimePath(projectRoot, "src/content/proposals"),
|
|
28
|
+
decisions: resolveRuntimePath(projectRoot, "src/content/decisions"),
|
|
29
|
+
people: resolveRuntimePath(projectRoot, "src/content/people"),
|
|
30
|
+
agents: resolveRuntimePath(projectRoot, "src/content/agents"),
|
|
31
|
+
books: resolveRuntimePath(projectRoot, "src/content/books"),
|
|
32
|
+
docs: resolveRuntimePath(projectRoot, "src/content/knowledge"),
|
|
33
|
+
templates: resolveRuntimePath(projectRoot, "src/content/templates"),
|
|
34
|
+
knowledge_packs: resolveRuntimePath(projectRoot, "src/content/knowledge-packs"),
|
|
35
|
+
workdays: resolveRuntimePath(projectRoot, "src/content/workdays")
|
|
27
36
|
},
|
|
28
37
|
features: {
|
|
29
38
|
docs: true,
|
|
@@ -40,15 +49,15 @@ const RUNTIME_TENANT = (() => {
|
|
|
40
49
|
if (injectedTenantConfig) {
|
|
41
50
|
return injectedTenantConfig;
|
|
42
51
|
}
|
|
43
|
-
|
|
44
|
-
return loadTreeseedManifest();
|
|
45
|
-
} catch {
|
|
46
|
-
return fallbackTenantConfig(RUNTIME_PROJECT_ROOT);
|
|
47
|
-
}
|
|
52
|
+
return fallbackTenantConfig(RUNTIME_PROJECT_ROOT);
|
|
48
53
|
})();
|
|
49
54
|
const RUNTIME_SITE_CONFIG = injectedSiteConfig ?? (() => {
|
|
55
|
+
const fs = getNodeBuiltin("fs");
|
|
56
|
+
if (!fs) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
50
59
|
try {
|
|
51
|
-
return parseSiteConfig(readFileSync(RUNTIME_TENANT.siteConfigPath, "utf8"));
|
|
60
|
+
return parseSiteConfig(fs.readFileSync(RUNTIME_TENANT.siteConfigPath, "utf8"));
|
|
52
61
|
} catch {
|
|
53
62
|
return null;
|
|
54
63
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { TreeseedContentCollection, TreeseedTenantConfig } from '@treeseed/sdk/platform/contracts';
|
|
2
|
-
export declare function isSiteRenderedModel(tenantConfig: Pick<TreeseedTenantConfig, 'features' | 'site'>, modelName: TreeseedContentCollection): boolean
|
|
2
|
+
export declare function isSiteRenderedModel(tenantConfig: Pick<TreeseedTenantConfig, 'features' | 'site'>, modelName: TreeseedContentCollection): boolean | Partial<Record<TreeseedContentCollection, import("@treeseed/sdk/platform/contracts").TreeseedTenantSiteModelConfig>>;
|
|
3
3
|
export declare function filterSiteRenderedModels<T extends {
|
|
4
4
|
model: TreeseedContentCollection;
|
|
5
5
|
}>(tenantConfig: Pick<TreeseedTenantConfig, 'features' | 'site'>, entries: T[]): T[];
|
|
6
|
-
export declare function siteModelRendered(modelName: TreeseedContentCollection): boolean
|
|
6
|
+
export declare function siteModelRendered(modelName: TreeseedContentCollection): boolean | Partial<Record<TreeseedContentCollection, import("@treeseed/sdk/platform/contracts").TreeseedTenantSiteModelConfig>>;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { tenantModelRendered } from "@treeseed/sdk/platform/tenant-config";
|
|
2
1
|
import { RUNTIME_TENANT } from "../tenant/runtime-config.js";
|
|
3
2
|
function isSiteRenderedModel(tenantConfig, modelName) {
|
|
4
|
-
|
|
3
|
+
const featureValue = tenantConfig.features?.[modelName];
|
|
4
|
+
const siteValue = tenantConfig.site?.[modelName];
|
|
5
|
+
return featureValue ?? siteValue ?? true;
|
|
5
6
|
}
|
|
6
7
|
function filterSiteRenderedModels(tenantConfig, entries) {
|
|
7
8
|
return entries.filter((entry) => isSiteRenderedModel(tenantConfig, entry.model));
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
BOOKS,
|
|
3
|
-
BOOKS_LINK,
|
|
4
|
-
TREESEED_LIBRARY_DOWNLOAD,
|
|
5
|
-
TREESEED_LINKS
|
|
6
|
-
} from "@treeseed/sdk/platform/books-data";
|
|
7
1
|
const normalizeHref = (href) => href.endsWith("/") ? href : `${href}/`;
|
|
8
2
|
function buildSidebarLink(href, label, currentPath) {
|
|
9
3
|
return {
|
|
@@ -82,6 +76,19 @@ function getDocsDownloadForPathFromRuntime(runtime2, pathname) {
|
|
|
82
76
|
downloadTitle: book.downloadTitle
|
|
83
77
|
};
|
|
84
78
|
}
|
|
79
|
+
const BOOKS = [];
|
|
80
|
+
const BOOKS_LINK = {
|
|
81
|
+
label: "Books",
|
|
82
|
+
link: "/knowledge/"
|
|
83
|
+
};
|
|
84
|
+
const TREESEED_LIBRARY_DOWNLOAD = {
|
|
85
|
+
downloadFileName: "treeseed-knowledge.md",
|
|
86
|
+
downloadHref: "/books/treeseed-knowledge.md",
|
|
87
|
+
downloadTitle: "TreeSeed Knowledge Library"
|
|
88
|
+
};
|
|
89
|
+
const TREESEED_LINKS = {
|
|
90
|
+
home: "/knowledge/"
|
|
91
|
+
};
|
|
85
92
|
const runtime = { BOOKS, BOOKS_LINK, TREESEED_LIBRARY_DOWNLOAD, TREESEED_LINKS };
|
|
86
93
|
function buildBookSidebar(bookSlug) {
|
|
87
94
|
return buildBookSidebarFromRuntime(runtime, bookSlug);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@treeseed/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "Treeseed integrated platform starter for Astro/Starlight web runtimes and Hono API runtimes.",
|
|
5
5
|
"license": "AGPL-3.0-only",
|
|
6
6
|
"repository": {
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"@astrojs/sitemap": "3.7.0",
|
|
76
76
|
"@astrojs/starlight": "0.37.6",
|
|
77
77
|
"@tailwindcss/vite": "^4.1.4",
|
|
78
|
-
"@treeseed/sdk": "^0.
|
|
78
|
+
"@treeseed/sdk": "^0.6.0",
|
|
79
79
|
"astro": "^5.6.1",
|
|
80
80
|
"esbuild": "^0.28.0",
|
|
81
81
|
"hono": "^4.8.2",
|