@treeseed/sdk 0.10.26 → 0.10.28

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 (28) hide show
  1. package/dist/index.d.ts +1 -1
  2. package/dist/index.js +8 -1
  3. package/dist/operations/services/mailpit-runtime.js +7 -4
  4. package/dist/operations/services/template-registry.js +14 -7
  5. package/dist/scripts/ensure-mailpit.js +23 -4
  6. package/dist/scripts/template-catalog.test.js +7 -7
  7. package/dist/sdk-types.d.ts +3 -1
  8. package/dist/sdk-types.js +8 -1
  9. package/dist/treeseed/template-catalog/catalog.fixture.json +489 -130
  10. package/package.json +1 -1
  11. package/dist/treeseed/template-catalog/templates/starter-basic/template/astro.config.d.ts +0 -3
  12. package/dist/treeseed/template-catalog/templates/starter-basic/template/astro.config.ts +0 -6
  13. package/dist/treeseed/template-catalog/templates/starter-basic/template/package.json +0 -35
  14. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/api/server.js +0 -4
  15. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/config.yaml +0 -65
  16. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/decisions/adopt-initial-proposal-loop.mdx +0 -22
  17. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/empty/.gitkeep +0 -1
  18. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/knowledge/handbook/index.mdx +0 -11
  19. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/pages/welcome.mdx +0 -11
  20. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/people/starter-steward.mdx +0 -11
  21. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/proposals/establish-initial-proposal-loop.mdx +0 -17
  22. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content.config.d.ts +0 -1
  23. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content.config.ts +0 -3
  24. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/env.yaml +0 -1
  25. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/manifest.yaml +0 -26
  26. package/dist/treeseed/template-catalog/templates/starter-basic/template/treeseed.site.yaml +0 -74
  27. package/dist/treeseed/template-catalog/templates/starter-basic/template/tsconfig.json +0 -9
  28. package/dist/treeseed/template-catalog/templates/starter-basic/template.config.json +0 -103
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { AgentSdk, ScopedAgentSdk } from './sdk.ts';
2
2
  export { ContentGraphRuntime } from './graph.ts';
3
- export { TREESEED_DEFAULT_STARTER_TEMPLATE_ID, projectConnectionModeFromHosting } from './sdk-types.ts';
3
+ export { TREESEED_DEFAULT_STARTER_TEMPLATE_ID, TREESEED_TEMPLATE_ID_ALIASES, normalizeTreeseedTemplateId, projectConnectionModeFromHosting, } from './sdk-types.ts';
4
4
  export { createControlPlaneReporter } from './control-plane.ts';
5
5
  export { ControlPlaneClient } from './control-plane-client.ts';
6
6
  export * from './seeds/index.ts';
package/dist/index.js CHANGED
@@ -1,6 +1,11 @@
1
1
  import { AgentSdk, ScopedAgentSdk } from "./sdk.js";
2
2
  import { ContentGraphRuntime } from "./graph.js";
3
- import { TREESEED_DEFAULT_STARTER_TEMPLATE_ID, projectConnectionModeFromHosting } from "./sdk-types.js";
3
+ import {
4
+ TREESEED_DEFAULT_STARTER_TEMPLATE_ID,
5
+ TREESEED_TEMPLATE_ID_ALIASES,
6
+ normalizeTreeseedTemplateId,
7
+ projectConnectionModeFromHosting
8
+ } from "./sdk-types.js";
4
9
  import { createControlPlaneReporter } from "./control-plane.js";
5
10
  import { ControlPlaneClient } from "./control-plane-client.js";
6
11
  export * from "./seeds/index.js";
@@ -395,6 +400,7 @@ export {
395
400
  TREESEED_MARKET_API_BASE_URL_ENV,
396
401
  TREESEED_REMOTE_CONTRACT_HEADER,
397
402
  TREESEED_REMOTE_CONTRACT_VERSION,
403
+ TREESEED_TEMPLATE_ID_ALIASES,
398
404
  TRESEED_OPERATION_SPECS,
399
405
  TeamScopedR2OverlayContentPublishProvider,
400
406
  TeamScopedR2OverlayContentRuntimeProvider,
@@ -528,6 +534,7 @@ export {
528
534
  normalizeTaskAdmissionPolicy,
529
535
  normalizeTaskPlanProposal,
530
536
  normalizeTemplateLaunchRequirements,
537
+ normalizeTreeseedTemplateId,
531
538
  normalizeUtilityPolicy,
532
539
  observeTreeseedUnits,
533
540
  parseGraphDsl,
@@ -1,5 +1,4 @@
1
1
  import { spawnSync } from "node:child_process";
2
- const EXPECTED_PORTS = ["1025->1025/tcp", "8025->8025/tcp"];
3
2
  const KNOWN_MAILPIT_NAMES = ["treeseed_mailpit", "docs_mailpit"];
4
3
  function runDocker(args, options = {}) {
5
4
  return spawnSync("docker", args, {
@@ -14,9 +13,13 @@ function parseDockerPsOutput(stdout) {
14
13
  });
15
14
  }
16
15
  function isCompatibleMailpitContainer(container) {
17
- const nameMatch = KNOWN_MAILPIT_NAMES.includes(container.name);
16
+ const expectedName = process.env.TREESEED_MAILPIT_CONTAINER_NAME?.trim();
17
+ const smtpPort = process.env.TREESEED_MAILPIT_SMTP_PORT?.trim() || "1025";
18
+ const uiPort = process.env.TREESEED_MAILPIT_UI_PORT?.trim() || "8025";
19
+ const expectedPorts = [`${smtpPort}->1025/tcp`, `${uiPort}->8025/tcp`];
20
+ const nameMatch = expectedName ? container.name === expectedName : KNOWN_MAILPIT_NAMES.includes(container.name);
18
21
  const imageMatch = container.image.includes("mailpit");
19
- const portsMatch = EXPECTED_PORTS.every((port) => container.ports.includes(port));
22
+ const portsMatch = expectedPorts.every((port) => container.ports.includes(port));
20
23
  return (nameMatch || imageMatch) && portsMatch;
21
24
  }
22
25
  function dockerIsAvailable() {
@@ -50,7 +53,7 @@ function stopKnownMailpitContainers(options = {}) {
50
53
  function streamKnownMailpitLogs() {
51
54
  const container = findRunningMailpitContainer();
52
55
  if (!container) {
53
- console.error("No running Mailpit container was found on ports 1025 and 8025.");
56
+ console.error("No running Mailpit container was found for the configured local ports.");
54
57
  process.exit(1);
55
58
  }
56
59
  const result = runDocker(["logs", "-f", container.name], { stdio: "inherit" });
@@ -1,6 +1,9 @@
1
1
  import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
2
2
  import { spawnSync } from "node:child_process";
3
3
  import { basename, dirname, relative, resolve } from "node:path";
4
+ import {
5
+ normalizeTreeseedTemplateId
6
+ } from "../../sdk-types.js";
4
7
  import { RemoteTemplateCatalogClient } from "../../template-catalog.js";
5
8
  import {
6
9
  normalizeTemplateLaunchRequirements
@@ -47,15 +50,15 @@ function listTemplateArtifactIds() {
47
50
  return [.../* @__PURE__ */ new Set([...packagedIds, ...localStarterIds])].sort((left, right) => left.localeCompare(right, void 0, { sensitivity: "base" }));
48
51
  }
49
52
  const LOCAL_STARTER_ID_TO_DIRECTORY = {
50
- "starter-research": "research",
51
- "starter-engineering": "engineering",
52
- "starter-information-hub": "information-hub"
53
+ "research": "research",
54
+ "engineering": "engineering",
55
+ "information-hub": "information-hub"
53
56
  };
54
57
  function localStartersRoot() {
55
58
  return resolve(cliPackageRoot, "..", "..", "starters");
56
59
  }
57
60
  function resolveLocalStarterArtifactRoot(id) {
58
- const directory = LOCAL_STARTER_ID_TO_DIRECTORY[id];
61
+ const directory = LOCAL_STARTER_ID_TO_DIRECTORY[normalizeTreeseedTemplateId(id)];
59
62
  if (!directory) {
60
63
  return null;
61
64
  }
@@ -124,11 +127,13 @@ function validateTemplatePlaceholders(definition) {
124
127
  }
125
128
  }
126
129
  function normalizeTemplateProduct(remoteProduct) {
127
- const artifactRoot = resolve(localTemplateArtifactsRoot, remoteProduct.id);
130
+ const id = normalizeTreeseedTemplateId(remoteProduct.id);
131
+ const artifactRoot = resolve(localTemplateArtifactsRoot, id);
128
132
  const source = remoteProduct.fulfillment.source;
129
133
  return {
130
134
  ...remoteProduct,
131
- contentPath: source.kind === "git" ? `${source.repoUrl}#${remoteProduct.id}` : `r2://${source.bucket ?? "bucket"}/${source.objectKey}#${remoteProduct.id}`,
135
+ id,
136
+ contentPath: source.kind === "git" ? `${source.repoUrl}#${id}` : `r2://${source.bucket ?? "bucket"}/${source.objectKey}#${id}`,
132
137
  artifactRoot,
133
138
  artifactManifestPath: resolve(artifactRoot, "template.config.json"),
134
139
  templateRoot: resolve(artifactRoot, "template"),
@@ -364,7 +369,8 @@ async function listTemplateProducts(options = {}) {
364
369
  });
365
370
  }
366
371
  async function resolveTemplateProduct(id, options = {}) {
367
- const product = (await listTemplateProducts(options)).find((entry) => entry.id === id);
372
+ const normalizedId = normalizeTreeseedTemplateId(id);
373
+ const product = (await listTemplateProducts(options)).find((entry) => entry.id === normalizedId);
368
374
  if (!product) {
369
375
  throw new Error(`Unable to resolve remote template product "${id}".`);
370
376
  }
@@ -524,6 +530,7 @@ async function syncTemplateProject(siteRoot, options = {}) {
524
530
  if (!check) {
525
531
  writeTemplateState(siteRoot, {
526
532
  ...state,
533
+ templateId: definition.product.id,
527
534
  templateVersion: definition.product.templateVersion,
528
535
  sourceRef: definition.product.fulfillment.source.ref,
529
536
  lastSyncedAt: (/* @__PURE__ */ new Date()).toISOString()
@@ -1,16 +1,35 @@
1
1
  import { spawnSync } from 'node:child_process';
2
2
  import { dockerIsAvailable, findRunningMailpitContainer } from '../operations/services/mailpit-runtime.js';
3
- import { mailpitComposeFile, packageRoot } from '../operations/services/runtime-paths.js';
3
+ import { packageRoot } from '../operations/services/runtime-paths.js';
4
+ function mailpitConfig() {
5
+ return {
6
+ containerName: process.env.TREESEED_MAILPIT_CONTAINER_NAME?.trim() || 'treeseed_mailpit',
7
+ smtpPort: process.env.TREESEED_MAILPIT_SMTP_PORT?.trim() || '1025',
8
+ uiPort: process.env.TREESEED_MAILPIT_UI_PORT?.trim() || '8025',
9
+ };
10
+ }
4
11
  if (!dockerIsAvailable()) {
5
12
  console.error('Docker is required for Treeseed form email testing. Start Docker and rerun the Mailpit command.');
6
13
  process.exit(1);
7
14
  }
8
15
  const existingMailpit = findRunningMailpitContainer();
16
+ const config = mailpitConfig();
9
17
  if (existingMailpit) {
10
- console.log(`Reusing existing Mailpit container "${existingMailpit.name}" on ports 1025 and 8025.`);
18
+ console.log(`Reusing existing Mailpit container "${existingMailpit.name}" on ports ${config.smtpPort} and ${config.uiPort}.`);
11
19
  process.exit(0);
12
20
  }
13
- const result = spawnSync('docker', ['compose', '-f', mailpitComposeFile, 'up', '-d', 'mailpit'], {
21
+ spawnSync('docker', ['rm', '-f', config.containerName], { encoding: 'utf8', cwd: packageRoot, env: { ...process.env } });
22
+ const result = spawnSync('docker', [
23
+ 'run',
24
+ '-d',
25
+ '--name',
26
+ config.containerName,
27
+ '-p',
28
+ `127.0.0.1:${config.smtpPort}:1025`,
29
+ '-p',
30
+ `127.0.0.1:${config.uiPort}:8025`,
31
+ 'axllent/mailpit:latest',
32
+ ], {
14
33
  encoding: 'utf8',
15
34
  cwd: packageRoot,
16
35
  env: { ...process.env },
@@ -18,7 +37,7 @@ const result = spawnSync('docker', ['compose', '-f', mailpitComposeFile, 'up', '
18
37
  if (result.status !== 0) {
19
38
  const reusedMailpit = findRunningMailpitContainer();
20
39
  if (reusedMailpit) {
21
- console.log(`Reusing existing Mailpit container "${reusedMailpit.name}" on ports 1025 and 8025.`);
40
+ console.log(`Reusing existing Mailpit container "${reusedMailpit.name}" on ports ${config.smtpPort} and ${config.uiPort}.`);
22
41
  process.exit(0);
23
42
  }
24
43
  if (result.stdout)
@@ -36,8 +36,8 @@ function writeCatalogCache(root, endpoint, items) {
36
36
  }
37
37
 
38
38
  const starterTemplate = {
39
- id: 'starter-basic',
40
- displayName: 'TreeSeed Basic',
39
+ id: 'fixture-template',
40
+ displayName: 'Fixture Template',
41
41
  description: 'Starter',
42
42
  summary: 'Starter summary',
43
43
  status: 'live',
@@ -53,7 +53,7 @@ const starterTemplate = {
53
53
  fulfillment: {
54
54
  source: {
55
55
  repoUrl: 'https://example.com/repo.git',
56
- directory: 'templates/starter-basic',
56
+ directory: 'templates/fixture-template',
57
57
  ref: 'main',
58
58
  },
59
59
  hooksPolicy: 'builtin_only',
@@ -69,7 +69,7 @@ test('template registry reads the remote catalog from a configured file endpoint
69
69
 
70
70
  const remoteProducts = await listTemplateProducts({ cwd, env: {} });
71
71
  assert.equal(remoteProducts.length, 1);
72
- assert.equal(remoteProducts[0]?.id, 'starter-basic');
72
+ assert.equal(remoteProducts[0]?.id, 'fixture-template');
73
73
 
74
74
  writeCatalogCache(cwd, fallbackEndpoint, [starterTemplate]);
75
75
 
@@ -83,7 +83,7 @@ test('template registry reads the remote catalog from a configured file endpoint
83
83
  });
84
84
 
85
85
  assert.equal(cachedProducts.length, 1);
86
- assert.equal(cachedProducts[0]?.id, 'starter-basic');
86
+ assert.equal(cachedProducts[0]?.id, 'fixture-template');
87
87
  assert.equal(warnings.length, 1);
88
88
  assert.match(warnings[0], /Using cached template catalog/);
89
89
  });
@@ -94,7 +94,7 @@ test('template definition resolution rejects templates missing from the remote c
94
94
  const cwd = makeMachineConfigRoot(`file:${fixturePath}`);
95
95
 
96
96
  await assert.rejects(
97
- () => resolveTemplateDefinition('starter-basic', { cwd, env: {} }),
98
- /Unable to resolve remote template product "starter-basic"\./,
97
+ () => resolveTemplateDefinition('fixture-template', { cwd, env: {} }),
98
+ /Unable to resolve remote template product "fixture-template"\./,
99
99
  );
100
100
  });
@@ -21,7 +21,9 @@ export declare const PROJECT_DEPLOYMENT_STATUSES: readonly ["pending", "queued",
21
21
  export declare const PROJECT_INFRA_RESOURCE_PROVIDERS: readonly ["cloudflare", "railway", "github", "market"];
22
22
  export declare const PROJECT_INFRA_RESOURCE_KINDS: readonly ["pages", "worker", "kv", "turnstile-widget", "r2", "d1", "queue", "dlq", "railway_project", "railway_service", "railway_schedule"];
23
23
  export declare const AGENT_POOL_STATUSES: readonly ["pending", "active", "degraded", "offline"];
24
- export declare const TREESEED_DEFAULT_STARTER_TEMPLATE_ID: "starter-research";
24
+ export declare const TREESEED_DEFAULT_STARTER_TEMPLATE_ID: "research";
25
+ export declare const TREESEED_TEMPLATE_ID_ALIASES: {};
26
+ export declare function normalizeTreeseedTemplateId(templateId: string | null | undefined): string;
25
27
  export declare const TEMPLATE_HOST_REQUIREMENT_TYPES: readonly ["repository", "web", "email", "ai"];
26
28
  export declare const TEMPLATE_RESOURCE_REQUIREMENT_TYPES: readonly ["service", "database", "object-storage", "queue", "dns-zone"];
27
29
  export declare const TEMPLATE_SECRET_SENSITIVITIES: readonly ["secret", "plain", "derived"];
package/dist/sdk-types.js CHANGED
@@ -59,7 +59,12 @@ const PROJECT_INFRA_RESOURCE_KINDS = [
59
59
  "railway_schedule"
60
60
  ];
61
61
  const AGENT_POOL_STATUSES = ["pending", "active", "degraded", "offline"];
62
- const TREESEED_DEFAULT_STARTER_TEMPLATE_ID = "starter-research";
62
+ const TREESEED_DEFAULT_STARTER_TEMPLATE_ID = "research";
63
+ const TREESEED_TEMPLATE_ID_ALIASES = {};
64
+ function normalizeTreeseedTemplateId(templateId) {
65
+ const trimmed = String(templateId ?? "").trim();
66
+ return TREESEED_TEMPLATE_ID_ALIASES[trimmed] ?? trimmed;
67
+ }
63
68
  const TEMPLATE_HOST_REQUIREMENT_TYPES = ["repository", "web", "email", "ai"];
64
69
  const TEMPLATE_RESOURCE_REQUIREMENT_TYPES = ["service", "database", "object-storage", "queue", "dns-zone"];
65
70
  const TEMPLATE_SECRET_SENSITIVITIES = ["secret", "plain", "derived"];
@@ -120,5 +125,7 @@ export {
120
125
  TREESEED_DEFAULT_STARTER_TEMPLATE_ID,
121
126
  TREESEED_HOSTING_KINDS,
122
127
  TREESEED_HOSTING_REGISTRATIONS,
128
+ TREESEED_TEMPLATE_ID_ALIASES,
129
+ normalizeTreeseedTemplateId,
123
130
  projectConnectionModeFromHosting
124
131
  };