@treeseed/core 0.6.49 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -4,7 +4,7 @@ export { parseSiteConfig } from './utils/site-config-schema.js';
4
4
  export { createTreeseedApiApp } from './api/app';
5
5
  export { createRailwayTreeseedApiServer } from './api/railway';
6
6
  export { resolveApiConfig } from './api/config';
7
- export { executeKnowledgeCoopManagedLaunch, validateKnowledgeCoopManagedLaunchPrerequisites, } from './launch';
7
+ export { executeKnowledgeHubProviderLaunch, validateKnowledgeHubProviderLaunchPrerequisites, } from './launch';
8
8
  export { createTreeseedIntegratedDevPlan, runTreeseedIntegratedDev, type TreeseedIntegratedDevCommand, type TreeseedIntegratedDevOptions, type TreeseedIntegratedDevPlan, type TreeseedIntegratedDevSurface, } from './dev';
9
9
  export { filterSiteRenderedModels, isSiteRenderedModel, siteModelRendered, } from './utils/site-models.ts';
10
10
  export type * from './api/types';
package/dist/index.js CHANGED
@@ -15,8 +15,8 @@ import { createTreeseedApiApp } from "./api/app.js";
15
15
  import { createRailwayTreeseedApiServer } from "./api/railway.js";
16
16
  import { resolveApiConfig } from "./api/config.js";
17
17
  import {
18
- executeKnowledgeCoopManagedLaunch,
19
- validateKnowledgeCoopManagedLaunchPrerequisites
18
+ executeKnowledgeHubProviderLaunch,
19
+ validateKnowledgeHubProviderLaunchPrerequisites
20
20
  } from "./launch.js";
21
21
  import {
22
22
  createTreeseedIntegratedDevPlan,
@@ -35,7 +35,7 @@ export {
35
35
  createRailwayTreeseedApiServer,
36
36
  createTreeseedApiApp,
37
37
  createTreeseedIntegratedDevPlan,
38
- executeKnowledgeCoopManagedLaunch,
38
+ executeKnowledgeHubProviderLaunch,
39
39
  filterSiteRenderedModels,
40
40
  isSiteRenderedModel,
41
41
  parseSiteConfig,
@@ -46,5 +46,5 @@ export {
46
46
  resolveTreeseedStyleEntrypoint,
47
47
  runTreeseedIntegratedDev,
48
48
  siteModelRendered,
49
- validateKnowledgeCoopManagedLaunchPrerequisites
49
+ validateKnowledgeHubProviderLaunchPrerequisites
50
50
  };
package/dist/launch.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import { executeKnowledgeCoopManagedLaunch, validateKnowledgeCoopManagedLaunchPrerequisites, type KnowledgeCoopManagedLaunchInput, type KnowledgeCoopManagedLaunchResult, type KnowledgeCoopLaunchPreflightReport } from '@treeseed/sdk';
2
- export { executeKnowledgeCoopManagedLaunch, validateKnowledgeCoopManagedLaunchPrerequisites, };
3
- export type { KnowledgeCoopManagedLaunchInput, KnowledgeCoopManagedLaunchResult, KnowledgeCoopLaunchPreflightReport, };
1
+ import { executeKnowledgeHubProviderLaunch, validateKnowledgeHubProviderLaunchPrerequisites, type KnowledgeHubProviderLaunchInput, type KnowledgeHubProviderLaunchResult, type KnowledgeHubProviderLaunchPreflightReport } from '@treeseed/sdk';
2
+ export { executeKnowledgeHubProviderLaunch, validateKnowledgeHubProviderLaunchPrerequisites, };
3
+ export type { KnowledgeHubProviderLaunchInput, KnowledgeHubProviderLaunchResult, KnowledgeHubProviderLaunchPreflightReport, };
package/dist/launch.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import {
2
- executeKnowledgeCoopManagedLaunch,
3
- validateKnowledgeCoopManagedLaunchPrerequisites
2
+ executeKnowledgeHubProviderLaunch,
3
+ validateKnowledgeHubProviderLaunchPrerequisites
4
4
  } from "@treeseed/sdk";
5
5
  export {
6
- executeKnowledgeCoopManagedLaunch,
7
- validateKnowledgeCoopManagedLaunchPrerequisites
6
+ executeKnowledgeHubProviderLaunch,
7
+ validateKnowledgeHubProviderLaunchPrerequisites
8
8
  };
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { fileURLToPath } from "node:url";
3
- import { AgentSdk, RemoteTreeseedClient, RemoteTreeseedRunnerClient } from "@treeseed/sdk";
3
+ import { AgentSdk, RemoteTreeseedClient, RemoteTreeseedRunnerClient, TreeseedOperationsSdk } from "@treeseed/sdk";
4
4
  import { createServiceSdk } from "./common.js";
5
5
  function integerFromEnv(name, fallback) {
6
6
  const value = process.env[name];
@@ -41,6 +41,79 @@ function createRunnerClient(config, fetchImpl) {
41
41
  fetchImpl
42
42
  }));
43
43
  }
44
+ function asRecord(value) {
45
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
46
+ }
47
+ function runnerWorkspacePaths(projectId) {
48
+ const volumeRoot = envValue("TREESEED_WORKER_VOLUME_ROOT") || "/data";
49
+ const workspaceRoot = `${volumeRoot}/workspaces/${projectId}`;
50
+ return {
51
+ root: workspaceRoot,
52
+ site: `${workspaceRoot}/site`,
53
+ content: `${workspaceRoot}/content`,
54
+ parent: `${workspaceRoot}/workspace-root`
55
+ };
56
+ }
57
+ function inputForRunnerJob(job) {
58
+ const input = asRecord(job.input);
59
+ if (job.namespace !== "content" || job.operation !== "publish") {
60
+ return input;
61
+ }
62
+ const paths = runnerWorkspacePaths(job.projectId);
63
+ return {
64
+ ...input,
65
+ tenantRoot: typeof input.tenantRoot === "string" ? input.tenantRoot : paths.site,
66
+ contentRepositoryRoot: typeof input.contentRepositoryRoot === "string" ? input.contentRepositoryRoot : paths.content,
67
+ workspaceRoot: typeof input.workspaceRoot === "string" ? input.workspaceRoot : paths.root
68
+ };
69
+ }
70
+ async function prepareLaunchIntentWithCredentialSessions(runner, jobId, launchJobInput, launchIntent) {
71
+ const sessions = asRecord(launchJobInput.credentialSessions);
72
+ const nextIntent = JSON.parse(JSON.stringify(launchIntent));
73
+ const execution = asRecord(nextIntent.execution);
74
+ const providerLaunchInput = asRecord(execution.providerLaunchInput);
75
+ const envOverlay = {};
76
+ const consume = async (key) => {
77
+ const sessionId = typeof sessions[key] === "string" ? sessions[key].trim() : "";
78
+ if (!sessionId || !runner) return null;
79
+ return (await runner.consumeCredentialSession(jobId, sessionId)).payload;
80
+ };
81
+ const repositorySession = await consume("repositoryHost");
82
+ if (repositorySession?.config) {
83
+ const token = repositorySession.config.GH_TOKEN ?? repositorySession.config.GITHUB_TOKEN;
84
+ if (token) {
85
+ envOverlay.GH_TOKEN = token;
86
+ envOverlay.GITHUB_TOKEN = repositorySession.config.GITHUB_TOKEN ?? token;
87
+ }
88
+ const owner = repositorySession.config.organizationOrOwner ?? repositorySession.config.owner;
89
+ if (owner) {
90
+ nextIntent.repository = {
91
+ ...asRecord(nextIntent.repository),
92
+ owner
93
+ };
94
+ providerLaunchInput.repoOwner = owner;
95
+ }
96
+ }
97
+ const webSession = await consume("webHost");
98
+ if (webSession?.config) {
99
+ providerLaunchInput.cloudflareHost = {
100
+ ...asRecord(providerLaunchInput.cloudflareHost),
101
+ config: webSession.config
102
+ };
103
+ }
104
+ const processingSession = await consume("processingHost");
105
+ if (processingSession?.config) {
106
+ providerLaunchInput.processingHost = {
107
+ ...asRecord(providerLaunchInput.processingHost),
108
+ config: processingSession.config
109
+ };
110
+ }
111
+ nextIntent.execution = {
112
+ ...execution,
113
+ providerLaunchInput
114
+ };
115
+ return { intent: nextIntent, envOverlay };
116
+ }
44
117
  async function runRemoteRunnerCycle(options = {}) {
45
118
  const config = options.config ?? resolveRemoteRunnerConfig();
46
119
  const sdk = options.sdk ?? createServiceSdk();
@@ -65,12 +138,58 @@ async function runRemoteRunnerCycle(options = {}) {
65
138
  status: "running"
66
139
  }
67
140
  });
68
- const result = await sdk.dispatch({
141
+ const launchJobInput = job.input && typeof job.input === "object" ? job.input : {};
142
+ const launchIntent = launchJobInput.launchIntent && typeof launchJobInput.launchIntent === "object" ? launchJobInput.launchIntent : launchJobInput;
143
+ const isLaunchJob = job.namespace === "workflow" && job.operation === "launch_project";
144
+ if (isLaunchJob) {
145
+ await runner.progress(job.id, {
146
+ summary: "Validating launch plan and preparing repository topology.",
147
+ data: {
148
+ runnerId: config.runnerId,
149
+ phase: "preflight_running",
150
+ status: "running",
151
+ title: "Validating launch plan"
152
+ }
153
+ });
154
+ }
155
+ const preparedLaunch = isLaunchJob ? await prepareLaunchIntentWithCredentialSessions(runner, job.id, launchJobInput, launchIntent) : null;
156
+ const result = isLaunchJob ? await new TreeseedOperationsSdk().execute({
157
+ operationName: launchJobInput.resume === true ? "hub.resume_launch" : "hub.execute_launch",
158
+ input: preparedLaunch?.intent ?? launchIntent
159
+ }, {
160
+ cwd: process.env.TREESEED_MARKET_REPO_ROOT?.trim() || process.cwd(),
161
+ env: {
162
+ ...process.env,
163
+ ...preparedLaunch?.envOverlay ?? {}
164
+ },
165
+ transport: "sdk",
166
+ onProgress: async (event) => {
167
+ if (event.kind !== "hub_launch_phase") return;
168
+ await runner.progress(job.id, {
169
+ summary: typeof event.summary === "string" ? event.summary : null,
170
+ data: {
171
+ ...event,
172
+ runnerId: config.runnerId
173
+ }
174
+ });
175
+ }
176
+ }) : await sdk.dispatch({
69
177
  namespace: job.namespace,
70
178
  operation: job.operation,
71
- input: job.input ?? {},
179
+ input: inputForRunnerJob(job),
72
180
  preferredMode: "prefer_local"
73
181
  });
182
+ if (isLaunchJob) {
183
+ await runner.progress(job.id, {
184
+ summary: "Launch execution completed; applying control-plane projections.",
185
+ data: {
186
+ runnerId: config.runnerId,
187
+ phase: "projection_running",
188
+ status: "running",
189
+ title: "Recording launch result"
190
+ }
191
+ });
192
+ }
74
193
  await runner.complete(job.id, {
75
194
  output: result.mode === "inline" ? result.payload : result
76
195
  });
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { mkdir } from "node:fs/promises";
2
+ import { mkdir, writeFile } from "node:fs/promises";
3
3
  import { join } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
5
  import { AgentKernel } from "../agents/kernel/agent-kernel.js";
@@ -28,6 +28,54 @@ function runnerRepositoryPath(volumeRoot, repositoryId, taskId) {
28
28
  worktree: join(repositoryRoot, "worktrees", taskId)
29
29
  };
30
30
  }
31
+ function runnerComposedWorkspacePath(volumeRoot, hubId) {
32
+ const workspaceRoot = join(volumeRoot, "workspaces", hubId);
33
+ return {
34
+ root: workspaceRoot,
35
+ parent: join(workspaceRoot, "workspace-root"),
36
+ site: join(workspaceRoot, "site"),
37
+ content: join(workspaceRoot, "content"),
38
+ manifest: join(workspaceRoot, ".treeseed", "workspace.json")
39
+ };
40
+ }
41
+ async function ensureRunnerComposedWorkspace(volumeRoot, task) {
42
+ const payload = parseTaskPayload(task);
43
+ const workspace = asRecord(payload.workspace);
44
+ const hubId = String(workspace.hubId ?? payload.projectId ?? task.projectId ?? "").trim();
45
+ if (!hubId) return null;
46
+ const paths = runnerComposedWorkspacePath(volumeRoot, hubId);
47
+ await mkdir(paths.parent, { recursive: true });
48
+ await mkdir(paths.site, { recursive: true });
49
+ await mkdir(paths.content, { recursive: true });
50
+ await mkdir(join(paths.root, ".treeseed"), { recursive: true });
51
+ await writeFile(paths.manifest, `${JSON.stringify({
52
+ schemaVersion: 1,
53
+ kind: "treeseed_composed_workspace",
54
+ hubId,
55
+ softwareRepository: workspace.softwareRepository ?? null,
56
+ contentRepository: workspace.contentRepository ?? null,
57
+ parentRepository: workspace.parentRepository ?? null,
58
+ paths: {
59
+ workspaceRoot: paths.parent,
60
+ site: paths.site,
61
+ content: paths.content
62
+ },
63
+ allowedWriteTargets: Array.isArray(workspace.allowedWriteTargets) ? workspace.allowedWriteTargets : ["content"],
64
+ credentialSessionScopes: workspace.credentialSessionScopes ?? {
65
+ software: ["repository:software"],
66
+ content: ["repository:content"],
67
+ parentWorkspace: []
68
+ },
69
+ credentialScopes: workspace.credentialScopes ?? {
70
+ software: ["repository:software"],
71
+ content: ["repository:content"],
72
+ parentWorkspace: []
73
+ },
74
+ contentOverlay: workspace.contentOverlay ?? "src_content_when_present"
75
+ }, null, 2)}
76
+ `, "utf8");
77
+ return paths;
78
+ }
31
79
  class WorkerPausedForApproval extends Error {
32
80
  constructor(request) {
33
81
  super(String(request.summary ?? request.title ?? "Task paused for approval."));
@@ -39,6 +87,10 @@ async function executeQueuedTask(options) {
39
87
  const context = await buildTaskContext(options.sdk, options.taskId);
40
88
  const task = context.task;
41
89
  const payload = parseTaskPayload(task);
90
+ await ensureRunnerComposedWorkspace(options.volumeRoot, {
91
+ ...task ?? {},
92
+ payloadJson: JSON.stringify(payload)
93
+ });
42
94
  const capacityEnvelope = readCapacityEnvelope(payload);
43
95
  const explicitApproval = asRecord(payload.approvalRequest);
44
96
  if (Object.keys(explicitApproval).length > 0 || capacityEnvelope?.maxCredits === 0) {
@@ -233,7 +285,8 @@ async function runWorkerCycle() {
233
285
  kernel,
234
286
  taskId: message.body.taskId,
235
287
  workerId: config.workerId,
236
- queueAttempt: message.attempts
288
+ queueAttempt: message.attempts,
289
+ volumeRoot: config.volumeRoot
237
290
  });
238
291
  } catch (error) {
239
292
  if (error instanceof WorkerPausedForApproval) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@treeseed/core",
3
- "version": "0.6.49",
3
+ "version": "0.7.0",
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": {
@@ -78,7 +78,7 @@
78
78
  "@astrojs/sitemap": "3.7.0",
79
79
  "@astrojs/starlight": "0.37.6",
80
80
  "@tailwindcss/vite": "^4.1.4",
81
- "@treeseed/sdk": "0.6.50",
81
+ "@treeseed/sdk": "0.7.0",
82
82
  "astro": "^5.6.1",
83
83
  "esbuild": "^0.28.0",
84
84
  "hono": "^4.8.2",